Subversion Repositories Kolibri OS

Rev

Rev 3884 | Rev 4021 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
9
;;     and Clevermouse.                                            ;;
10
;;                                                                 ;;
11
;;       Based on code by mike.dld                                 ;;
12
;;                                                                 ;;
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
18
$Revision: 3514 $
19
 
20
struct  SOCKET
21
 
22
        NextPtr                 dd ? ; pointer to next socket in list
23
        PrevPtr                 dd ? ; pointer to previous socket in list
24
        Number                  dd ? ; socket number
25
 
26
        mutex                   MUTEX
27
 
28
        PID                     dd ? ; process ID
29
        TID                     dd ? ; thread ID
30
        Domain                  dd ? ; INET/LOCAL/..
31
        Type                    dd ? ; RAW/STREAM/DGRAP
32
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
33
        errorcode               dd ?
34
        device                  dd ? ; driver pointer, socket pointer if it's an LOCAL socket
35
 
36
        options                 dd ?
37
        state                   dd ?
38
        backlog                 dw ? ; how many incoming connections that can be queued
39
 
40
        snd_proc                dd ?
41
        rcv_proc                dd ?
42
 
43
ends
44
 
45
struct  IP_SOCKET               SOCKET
46
 
47
        LocalIP                 rd 4 ; network byte order
48
        RemoteIP                rd 4 ; network byte order
49
 
50
ends
51
 
52
struct  TCP_SOCKET              IP_SOCKET
53
 
54
        LocalPort               dw ? ; network byte order
55
        RemotePort              dw ? ; network byte order
56
 
57
        t_state                 dd ? ; TCB state
58
        t_rxtshift              db ?
59
                                rb 3 ; align
60
        t_rxtcur                dd ?
61
        t_dupacks               dd ?
62
        t_maxseg                dd ?
63
        t_force                 dd ?
64
        t_flags                 dd ?
65
 
66
;---------------
67
; RFC783 page 21
68
 
69
; send sequence
70
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
71
        SND_NXT                 dd ? ; next send sequence number to use
72
        SND_UP                  dd ? ; urgent pointer
73
        SND_WL1                 dd ? ; window minus one
74
        SND_WL2                 dd ? ;
75
        ISS                     dd ? ; initial send sequence number
76
        SND_WND                 dd ? ; send window
77
 
78
; receive sequence
79
        RCV_WND                 dd ? ; receive window
80
        RCV_NXT                 dd ? ; next receive sequence number to use
81
        RCV_UP                  dd ? ; urgent pointer
82
        IRS                     dd ? ; initial receive sequence number
83
 
84
;---------------------
85
; Additional variables
86
 
87
; receive variables
88
        RCV_ADV                 dd ?
89
 
90
; retransmit variables
91
        SND_MAX                 dd ?
92
 
93
; congestion control
94
        SND_CWND                dd ?
95
        SND_SSTHRESH            dd ?
96
 
97
;----------------------
98
; Transmit timing stuff
99
        t_idle                  dd ?
100
        t_rtt                   dd ?
101
        t_rtseq                 dd ?
102
        t_srtt                  dd ?
103
        t_rttvar                dd ?
104
        t_rttmin                dd ?
105
        max_sndwnd              dd ?
106
 
107
;-----------------
108
; Out-of-band data
109
        t_oobflags              dd ?
110
        t_iobc                  dd ?
111
        t_softerror             dd ?
112
 
113
 
114
;---------
115
; RFC 1323                              ; the order of next 4 elements may not change
116
 
117
        SND_SCALE               db ?
118
        RCV_SCALE               db ?
119
        requested_s_scale       db ?
120
        request_r_scale         db ?
121
 
122
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
123
        ts_recent_age           dd ?
124
        last_ack_sent           dd ?
125
 
126
 
127
;-------
128
; Timers
3600 hidnplayr 129
        timer_flags             dd ?
3545 hidnplayr 130
        timer_retransmission    dd ? ; rexmt
131
        timer_persist           dd ?
132
        timer_keepalive         dd ? ; keepalive/syn timeout
133
        timer_timed_wait        dd ? ; also used as 2msl timer
134
 
135
; extra
136
 
137
        ts_ecr                  dd ? ; timestamp echo reply
138
        ts_val                  dd ?
139
 
140
        seg_next                dd ? ; re-assembly queue
141
 
142
        temp_bits               db ?
143
                                rb 3 ; align
144
 
145
ends
146
 
147
struct  UDP_SOCKET              IP_SOCKET
148
 
149
        LocalPort               dw ? ; network byte order
150
        RemotePort              dw ? ; network byte order
151
        firstpacket             db ?
152
 
153
ends
154
 
155
 
156
struct  ICMP_SOCKET             IP_SOCKET
157
 
158
        Identifier              dw ?
159
 
160
ends
161
 
162
 
163
struct  RING_BUFFER
164
 
165
        mutex                   MUTEX
166
        start_ptr               dd ? ; Pointer to start of buffer
167
        end_ptr                 dd ? ; pointer to end of buffer
168
        read_ptr                dd ? ; Read pointer
169
        write_ptr               dd ? ; Write pointer
170
        size                    dd ? ; Number of bytes buffered
171
 
172
ends
173
 
174
struct  STREAM_SOCKET           TCP_SOCKET
175
 
176
        rcv                     RING_BUFFER
177
        snd                     RING_BUFFER
178
 
179
ends
180
 
181
struct  socket_queue_entry
182
 
183
        data_ptr                dd ?
184
        buf_ptr                 dd ?
185
        data_size               dd ?
186
 
187
ends
188
 
189
 
190
SOCKETBUFFSIZE          = 4096     ; in bytes
191
 
192
SOCKET_QUEUE_SIZE       = 10       ; maximum number of incoming packets queued for 1 socket
193
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
194
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
195
 
196
uglobal
3698 hidnplayr 197
align 4
198
 
3545 hidnplayr 199
        net_sockets     rd 4
200
        last_socket_num dd ?
201
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
202
        last_TCP_port   dw ? ;
3647 hidnplayr 203
        socket_mutex    MUTEX
3698 hidnplayr 204
 
3545 hidnplayr 205
endg
206
 
207
 
208
;-----------------------------------------------------------------
209
;
210
; SOCKET_init
211
;
212
;-----------------------------------------------------------------
213
macro   SOCKET_init {
214
 
215
        xor     eax, eax
216
        mov     edi, net_sockets
217
        mov     ecx, 5
3711 clevermous 218
        rep stosd
3545 hidnplayr 219
 
220
       @@:
221
        pseudo_random eax
3600 hidnplayr 222
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 223
        jb      @r
3600 hidnplayr 224
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 225
        ja      @r
226
        xchg    al, ah
227
        mov     [last_UDP_port], ax
228
 
229
       @@:
230
        pseudo_random eax
3600 hidnplayr 231
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 232
        jb      @r
3600 hidnplayr 233
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 234
        ja      @r
235
        xchg    al, ah
236
        mov     [last_TCP_port], ax
237
 
3647 hidnplayr 238
        mov     ecx, socket_mutex
239
        call    mutex_init
240
 
3545 hidnplayr 241
}
242
 
243
;-----------------------------------------------------------------
244
;
245
; Socket API (function 74)
246
;
247
;-----------------------------------------------------------------
248
align 4
249
sys_socket:
250
 
3673 hidnplayr 251
        mov     dword[esp+20], 0        ; Set error code to 0
3659 hidnplayr 252
 
3545 hidnplayr 253
        cmp     ebx, 255
254
        jz      SOCKET_debug
255
 
256
        cmp     ebx, .number
3658 hidnplayr 257
        ja      .error
3545 hidnplayr 258
        jmp     dword [.table + 4*ebx]
259
 
260
  .table:
261
        dd      SOCKET_open     ; 0
262
        dd      SOCKET_close    ; 1
263
        dd      SOCKET_bind     ; 2
264
        dd      SOCKET_listen   ; 3
265
        dd      SOCKET_connect  ; 4
266
        dd      SOCKET_accept   ; 5
267
        dd      SOCKET_send     ; 6
268
        dd      SOCKET_receive  ; 7
269
        dd      SOCKET_set_opt  ; 8
270
        dd      SOCKET_get_opt  ; 9
271
        dd      SOCKET_pair     ; 10
272
  .number = ($ - .table) / 4 - 1
273
 
3658 hidnplayr 274
  .error:
275
        mov     dword[esp+32], -1
3673 hidnplayr 276
        mov     dword[esp+20], EINVAL
3545 hidnplayr 277
 
278
        ret
279
 
280
;-----------------------------------------------------------------
281
;
282
; SOCKET_open
283
;
284
;  IN:  domain in ecx
285
;       type in edx
286
;       protocol in esi
287
;  OUT: eax is socket num, -1 on error
288
;
289
;-----------------------------------------------------------------
290
align 4
291
SOCKET_open:
292
 
3556 hidnplayr 293
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
3545 hidnplayr 294
 
295
        push    ecx edx esi
296
        call    SOCKET_alloc
297
        pop     esi edx ecx
3658 hidnplayr 298
        jz      .nobuffs
3545 hidnplayr 299
 
300
        mov     [esp+32], edi                   ; return socketnumber
3556 hidnplayr 301
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
3545 hidnplayr 302
 
3705 hidnplayr 303
        test    edx, SO_NONBLOCK
304
        jz      @f
305
        or      [eax + SOCKET.options], SO_NONBLOCK
306
        and     edx, not SO_NONBLOCK
307
  @@:
3545 hidnplayr 308
 
309
        mov     [eax + SOCKET.Domain], ecx
310
        mov     [eax + SOCKET.Type], edx
311
        mov     [eax + SOCKET.Protocol], esi
312
 
313
        cmp     ecx, AF_INET4
314
        jne     .no_inet4
315
 
316
        cmp     edx, SOCK_DGRAM
317
        je      .udp
318
 
319
        cmp     edx, SOCK_STREAM
320
        je      .tcp
321
 
322
        cmp     edx, SOCK_RAW
323
        je      .raw
324
 
325
  .no_inet4:
326
        cmp     ecx, AF_PPP
327
        jne     .no_ppp
328
 
329
        cmp     esi, PPP_PROTO_ETHERNET
330
        je      .pppoe
331
 
332
  .no_ppp:
3658 hidnplayr 333
  .unsupported:
334
        push    eax
335
        call    SOCKET_free
336
        pop     eax
3673 hidnplayr 337
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 338
        mov     dword[esp+32], -1
3545 hidnplayr 339
        ret
340
 
3658 hidnplayr 341
  .nobuffs:
3673 hidnplayr 342
        mov     dword[esp+20], ENOBUFS
3658 hidnplayr 343
        mov     dword[esp+32], -1
344
        ret
345
 
3545 hidnplayr 346
  .raw:
347
        test    esi, esi       ; IP_PROTO_IP
3658 hidnplayr 348
        jz      .raw_ip
3545 hidnplayr 349
 
350
        cmp     esi, IP_PROTO_ICMP
3658 hidnplayr 351
        je      .raw_icmp
3545 hidnplayr 352
 
3658 hidnplayr 353
        jmp     .unsupported
3545 hidnplayr 354
 
355
align 4
356
  .udp:
357
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
358
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
359
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
360
        ret
361
 
362
align 4
363
  .tcp:
364
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
365
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
366
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
367
 
368
        TCP_init_socket eax
369
        ret
370
 
371
 
372
align 4
3658 hidnplayr 373
  .raw_ip:
3545 hidnplayr 374
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
375
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
376
        ret
377
 
378
 
379
align 4
3658 hidnplayr 380
  .raw_icmp:
3545 hidnplayr 381
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
382
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
383
        ret
384
 
385
align 4
386
  .pppoe:
387
        push    eax
388
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
389
        pop     eax
390
 
391
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
392
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
393
        ret
394
 
395
 
396
;-----------------------------------------------------------------
397
;
398
; SOCKET_bind
399
;
400
;  IN:  socket number in ecx
401
;       pointer to sockaddr struct in edx
402
;       length of that struct in esi
403
;  OUT: 0 on success
404
;
405
;-----------------------------------------------------------------
406
align 4
407
SOCKET_bind:
408
 
3556 hidnplayr 409
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 410
 
411
        call    SOCKET_num_to_ptr
3658 hidnplayr 412
        jz      .invalid
3545 hidnplayr 413
 
414
        cmp     esi, 2
3658 hidnplayr 415
        jb      .invalid
3545 hidnplayr 416
 
417
        cmp     word [edx], AF_INET4
418
        je      .af_inet4
419
 
420
        cmp     word [edx], AF_LOCAL
421
        je      .af_local
422
 
3658 hidnplayr 423
  .notsupp:
3673 hidnplayr 424
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 425
        mov     dword[esp+32], -1
426
        ret
3545 hidnplayr 427
 
3658 hidnplayr 428
  .invalid:
3673 hidnplayr 429
        mov     dword[esp+20], EINVAL
3658 hidnplayr 430
        mov     dword[esp+32], -1
431
        ret
432
 
3545 hidnplayr 433
  .af_local:
434
        ; TODO: write code here
3658 hidnplayr 435
        mov     dword[esp+32], 0
3545 hidnplayr 436
        ret
437
 
438
  .af_inet4:
439
        cmp     esi, 6
3658 hidnplayr 440
        jb      .invalid
3545 hidnplayr 441
 
442
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
443
        je      .udp
444
 
445
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
446
        je      .tcp
447
 
3658 hidnplayr 448
        jmp     .notsupp
3545 hidnplayr 449
 
450
  .tcp:
451
  .udp:
3637 hidnplayr 452
        mov     ebx, [edx + 4]                  ; First, fill in the IP
3545 hidnplayr 453
        test    ebx, ebx                        ; If IP is 0, use default
454
        jnz     @f
3601 hidnplayr 455
        mov     ebx, [IP_LIST + 4]      ;;;;; FIXME !i!i!i
3545 hidnplayr 456
       @@:
457
        mov     [eax + IP_SOCKET.LocalIP], ebx
458
 
459
        mov     bx, [edx + 2]                   ; Now fill in the local port if it's still available
460
        call    SOCKET_check_port
3658 hidnplayr 461
        jz      .addrinuse                      ; ZF is set by socket_check_port, on error
3545 hidnplayr 462
 
3556 hidnplayr 463
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3545 hidnplayr 464
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
465
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
466
 
3658 hidnplayr 467
        mov     dword[esp+32], 0
3545 hidnplayr 468
        ret
469
 
3658 hidnplayr 470
  .addrinuse:
471
        mov     dword[esp+32], -1
3673 hidnplayr 472
        mov     dword[esp+20], EADDRINUSE
3658 hidnplayr 473
        ret
3545 hidnplayr 474
 
475
 
476
 
3658 hidnplayr 477
 
3545 hidnplayr 478
;-----------------------------------------------------------------
479
;
480
; SOCKET_connect
481
;
482
;  IN:  socket number in ecx
483
;       pointer to sockaddr struct in edx
484
;       length of that struct in esi
485
;  OUT: 0 on success
486
;
487
;-----------------------------------------------------------------
488
align 4
489
SOCKET_connect:
490
 
3556 hidnplayr 491
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 492
 
493
        call    SOCKET_num_to_ptr
3658 hidnplayr 494
        jz      .invalid
3545 hidnplayr 495
 
496
        cmp     esi, 8
3658 hidnplayr 497
        jb      .invalid
3545 hidnplayr 498
 
499
        cmp     word [edx], AF_INET4
500
        je      .af_inet4
501
 
3658 hidnplayr 502
  .notsupp:
3673 hidnplayr 503
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 504
        mov     dword[esp+32], -1
505
        ret
3545 hidnplayr 506
 
3658 hidnplayr 507
  .invalid:
3673 hidnplayr 508
        mov     dword[esp+20], EINVAL
3658 hidnplayr 509
        mov     dword[esp+32], -1
510
        ret
511
 
3545 hidnplayr 512
  .af_inet4:
513
        cmp     [eax + IP_SOCKET.LocalIP], 0
514
        jne     @f
3601 hidnplayr 515
        push    [IP_LIST + 4]                               ; FIXME !i!i!i!
3545 hidnplayr 516
        pop     [eax + IP_SOCKET.LocalIP]
517
       @@:
518
 
519
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
520
        je      .udp
521
 
522
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
523
        je      .tcp
524
 
525
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
526
        je      .ip
527
 
528
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
529
        je      .ip
530
 
3658 hidnplayr 531
        jmp     .notsupp
3545 hidnplayr 532
 
533
align 4
534
  .udp:
535
        pusha
536
        lea     ecx, [eax + SOCKET.mutex]
537
        call    mutex_lock
538
        popa
539
 
540
        pushw   [edx + 2]
541
        pop     [eax + UDP_SOCKET.RemotePort]
542
 
543
        pushd   [edx + 4]
544
        pop     [eax + IP_SOCKET.RemoteIP]
545
 
546
        cmp     [eax + UDP_SOCKET.LocalPort], 0
547
        jne     @f
548
        call    SOCKET_find_port
549
       @@:
550
 
551
        mov     [eax + UDP_SOCKET.firstpacket], 0
552
 
553
        push    eax
554
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
555
        pop     eax
556
 
557
        lea     ecx, [eax + SOCKET.mutex]
558
        call    mutex_unlock
559
 
3658 hidnplayr 560
        mov     dword[esp+32], 0
3545 hidnplayr 561
        ret
562
 
563
align 4
564
  .tcp:
565
        pusha
566
        lea     ecx, [eax + SOCKET.mutex]
567
        call    mutex_lock
568
        popa
569
 
570
        pushw   [edx + 2]
571
        pop     [eax + TCP_SOCKET.RemotePort]
572
 
573
        pushd   [edx + 4]
574
        pop     [eax + IP_SOCKET.RemoteIP]
575
 
576
        cmp     [eax + TCP_SOCKET.LocalPort], 0
577
        jne     @f
578
        call    SOCKET_find_port
579
       @@:
580
 
581
        mov     [eax + TCP_SOCKET.timer_persist], 0
582
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
583
 
584
        push    [TCP_sequence_num]
585
        add     [TCP_sequence_num], 6400
586
        pop     [eax + TCP_SOCKET.ISS]
587
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
588
 
589
        TCP_sendseqinit eax
590
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
591
 
592
        mov     ebx, eax
593
        lea     eax, [ebx + STREAM_SOCKET.snd]
3658 hidnplayr 594
        call    SOCKET_ring_create              ; TODO: check if memory was available or not
3545 hidnplayr 595
 
596
        lea     eax, [ebx + STREAM_SOCKET.rcv]
3658 hidnplayr 597
        call    SOCKET_ring_create              ; TODO: same here
3545 hidnplayr 598
 
599
        pusha
600
        lea     ecx, [ebx + SOCKET.mutex]
601
        call    mutex_unlock
602
        popa
603
 
3674 hidnplayr 604
        push    ebx
3545 hidnplayr 605
        mov     eax, ebx
606
        call    TCP_output
3674 hidnplayr 607
        pop     eax
3545 hidnplayr 608
 
3674 hidnplayr 609
  .block:
610
        test    [eax + SOCKET.options], SO_NONBLOCK
4020 hidnplayr 611
        jz      .waitforit
3545 hidnplayr 612
 
3674 hidnplayr 613
        mov     dword[esp+20], EWOULDBLOCK
3704 hidnplayr 614
        mov     dword[esp+32], -1
3674 hidnplayr 615
        ret
616
 
4020 hidnplayr 617
  .waitforit:
618
        push    eax
619
        stdcall timer_hs, 300, 0, .wake, eax            ; FIXME: make timeout a constant
620
        pop     eax
621
 
3674 hidnplayr 622
  .loop:
4020 hidnplayr 623
        cmp     [eax + SOCKET.errorcode], 0
624
        jne     .fail
3698 hidnplayr 625
        cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
626
        je      .established
3674 hidnplayr 627
 
628
        call    SOCKET_block
629
        jmp     .loop
630
 
4020 hidnplayr 631
  .wake:
632
        mov     eax, [esp+4]
633
        mov     [eax + SOCKET.errorcode], ETIMEDOUT
634
        call    SOCKET_notify.unblock
635
        ret     4
636
 
3674 hidnplayr 637
  .fail:
638
        mov     eax, [eax + SOCKET.errorcode]
639
        mov     [esp+20], eax
640
        mov     dword[esp+32], -1
641
        ret
642
 
3698 hidnplayr 643
  .established:
3658 hidnplayr 644
        mov     dword[esp+32], 0
3545 hidnplayr 645
        ret
646
 
3674 hidnplayr 647
 
3545 hidnplayr 648
align 4
649
  .ip:
650
        pusha
651
        lea     ecx, [eax + SOCKET.mutex]
652
        call    mutex_lock
653
        popa
654
 
655
        pushd   [edx + 4]
656
        pop     [eax + IP_SOCKET.RemoteIP]
657
 
658
        push    eax
659
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
660
        pop     eax
661
 
662
        lea     ecx, [eax + SOCKET.mutex]
663
        call    mutex_unlock
664
 
3658 hidnplayr 665
        mov     dword[esp+32], 0
3545 hidnplayr 666
        ret
667
 
668
 
669
;-----------------------------------------------------------------
670
;
671
; SOCKET_listen
672
;
673
;  IN:  socket number in ecx
674
;       backlog in edx
675
;  OUT: eax is socket num, -1 on error
676
;
677
;-----------------------------------------------------------------
678
align 4
679
SOCKET_listen:
680
 
3556 hidnplayr 681
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3545 hidnplayr 682
 
683
        call    SOCKET_num_to_ptr
3658 hidnplayr 684
        jz      .invalid
3545 hidnplayr 685
 
686
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 687
        jne     .notsupp
3545 hidnplayr 688
 
689
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 690
        jne     .invalid
3545 hidnplayr 691
 
692
        cmp     [eax + TCP_SOCKET.LocalPort], 0
3658 hidnplayr 693
        je      .already
3545 hidnplayr 694
 
695
        cmp     [eax + IP_SOCKET.LocalIP], 0
696
        jne     @f
3601 hidnplayr 697
        push    [IP_LIST + 4]           ;;; fixme!!!!
3545 hidnplayr 698
        pop     [eax + IP_SOCKET.LocalIP]
699
       @@:
700
 
701
        cmp     edx, MAX_backlog
702
        jbe     @f
703
        mov     edx, MAX_backlog
704
       @@:
705
 
706
        mov     [eax + SOCKET.backlog], dx
707
        or      [eax + SOCKET.options], SO_ACCEPTCON
708
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
709
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
710
 
711
        push    eax
712
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
713
        pop     eax
714
 
3658 hidnplayr 715
        mov     dword[esp+32], 0
716
        ret
3545 hidnplayr 717
 
3658 hidnplayr 718
  .notsupp:
3673 hidnplayr 719
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 720
        mov     dword[esp+32], -1
3545 hidnplayr 721
        ret
722
 
3658 hidnplayr 723
  .invalid:
3673 hidnplayr 724
        mov     dword[esp+20], EINVAL
3658 hidnplayr 725
        mov     dword[esp+32], -1
726
        ret
3545 hidnplayr 727
 
3658 hidnplayr 728
  .already:
3673 hidnplayr 729
        mov     dword[esp+20], EALREADY
3658 hidnplayr 730
        mov     dword[esp+32], -1
731
        ret
732
 
733
 
3545 hidnplayr 734
;-----------------------------------------------------------------
735
;
736
; SOCKET_accept
737
;
738
;  IN:  socket number in ecx
739
;       addr in edx
740
;       addrlen in esi
741
;  OUT: eax is socket num, -1 on error
742
;
743
;-----------------------------------------------------------------
744
align 4
745
SOCKET_accept:
746
 
3556 hidnplayr 747
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 748
 
749
        call    SOCKET_num_to_ptr
3658 hidnplayr 750
        jz      .invalid
3545 hidnplayr 751
 
752
        test    [eax + SOCKET.options], SO_ACCEPTCON
3658 hidnplayr 753
        jz      .invalid
3545 hidnplayr 754
 
755
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 756
        jne     .notsupp
3545 hidnplayr 757
 
758
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 759
        jne     .invalid
3545 hidnplayr 760
 
761
  .loop:
762
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
763
 
764
; Ok, we got a socket ptr
765
        mov     eax, [esi]
766
 
767
; Change thread ID to that of the current thread
768
        mov     ebx, [TASK_BASE]
769
        mov     ebx, [ebx + TASKDATA.pid]
770
        mov     [eax + SOCKET.TID], ebx
771
 
3817 hidnplayr 772
; Convert it to a socket number
773
        call    SOCKET_ptr_to_num
774
        jz      .invalid        ; FIXME ?
775
 
3545 hidnplayr 776
; and return it to caller
777
        mov     [esp+32], eax
778
        ret
779
 
780
  .block:
781
        test    [eax + SOCKET.options], SO_NONBLOCK
3658 hidnplayr 782
        jnz     .wouldblock
3545 hidnplayr 783
 
784
        call    SOCKET_block
785
        jmp     .loop
786
 
3658 hidnplayr 787
  .wouldblock:
3673 hidnplayr 788
        mov     dword[esp+20], EWOULDBLOCK
3658 hidnplayr 789
        mov     dword[esp+32], -1
790
        ret
791
 
792
  .invalid:
3673 hidnplayr 793
        mov     dword[esp+20], EINVAL
3658 hidnplayr 794
        mov     dword[esp+32], -1
795
        ret
796
 
797
  .notsupp:
3673 hidnplayr 798
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 799
        mov     dword[esp+32], -1
800
        ret
801
 
3545 hidnplayr 802
;-----------------------------------------------------------------
803
;
804
; SOCKET_close
805
;
806
;  IN:  socket number in ecx
807
;  OUT: eax is socket num, -1 on error
808
;
809
;-----------------------------------------------------------------
810
align 4
811
SOCKET_close:
812
 
3556 hidnplayr 813
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3545 hidnplayr 814
 
815
        call    SOCKET_num_to_ptr
3658 hidnplayr 816
        jz      .invalid
3545 hidnplayr 817
 
3658 hidnplayr 818
        mov     dword[esp+32], 0                                ; The socket exists, so we will succeed in closing it.
3545 hidnplayr 819
 
820
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
821
 
822
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
823
        jz      @f
824
        call    SOCKET_notify.unblock                           ; Unblock it.
825
  @@:
826
 
827
        cmp     [eax + SOCKET.Domain], AF_INET4
828
        jne     .free
829
 
830
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
831
        je      .tcp
832
 
833
  .free:
834
        call    SOCKET_free
835
        ret
836
 
837
  .tcp:
838
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
839
        jb      .free
840
 
841
        call    TCP_usrclosed
842
        call    TCP_output      ;;;; Fixme: is this nescessary??
3646 hidnplayr 843
        call    SOCKET_free
3545 hidnplayr 844
 
845
        ret
846
 
847
 
3658 hidnplayr 848
  .invalid:
3673 hidnplayr 849
        mov     dword[esp+20], EINVAL
3658 hidnplayr 850
        mov     dword[esp+32], -1
851
        ret
852
 
853
 
3545 hidnplayr 854
;-----------------------------------------------------------------
855
;
856
; SOCKET_receive
857
;
858
;  IN:  socket number in ecx
859
;       addr to buffer in edx
860
;       length of buffer in esi
861
;       flags in edi
862
;  OUT: eax is number of bytes copied, -1 on error
863
;
864
;-----------------------------------------------------------------
865
align 4
866
SOCKET_receive:
867
 
3556 hidnplayr 868
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 869
 
870
        call    SOCKET_num_to_ptr
3658 hidnplayr 871
        jz      .invalid
3545 hidnplayr 872
 
3704 hidnplayr 873
  .loop:
874
        push    edi
3565 hidnplayr 875
        call    [eax + SOCKET.rcv_proc]
3704 hidnplayr 876
        pop     edi
3545 hidnplayr 877
 
3704 hidnplayr 878
        cmp     ebx, EWOULDBLOCK
879
        jne     .return
880
 
881
        test    edi, MSG_DONTWAIT
882
        jnz     .return_err
883
 
3737 hidnplayr 884
        test    [eax + SOCKET.state], SS_CANTRCVMORE
885
        jnz     .return_err
886
 
3704 hidnplayr 887
;        test    [eax + SOCKET.options], SO_NONBLOCK
888
;        jnz     .return_err
889
 
890
        call    SOCKET_block
891
        jmp     .loop
892
 
893
 
894
  .invalid:
895
        push    EINVAL
896
        pop     ebx
897
  .return_err:
898
        mov     eax, -1
899
  .return:
3673 hidnplayr 900
        mov     [esp+20], ebx
3565 hidnplayr 901
        mov     [esp+32], eax
902
        ret
3545 hidnplayr 903
 
3565 hidnplayr 904
 
3658 hidnplayr 905
 
3704 hidnplayr 906
 
907
 
3545 hidnplayr 908
align 4
909
SOCKET_receive_dgram:
3704 hidnplayr 910
 
3556 hidnplayr 911
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 912
 
3704 hidnplayr 913
        mov     ebx, esi                                        ; bufferlength
3545 hidnplayr 914
 
3704 hidnplayr 915
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
3545 hidnplayr 916
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 917
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 918
 
3704 hidnplayr 919
        cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
3545 hidnplayr 920
        ja      .too_small
921
 
3565 hidnplayr 922
        push    ecx
3545 hidnplayr 923
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
924
        mov     esi, [esi + socket_queue_entry.data_ptr]
3556 hidnplayr 925
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 926
 
3704 hidnplayr 927
; copy the data from kernel buffer to application buffer
928
        mov     edi, edx                                        ; bufferaddr
3545 hidnplayr 929
        shr     ecx, 1
930
        jnc     .nb
931
        movsb
932
  .nb:
933
        shr     ecx, 1
934
        jnc     .nw
935
        movsw
936
  .nw:
937
        test    ecx, ecx
938
        jz      .nd
3711 clevermous 939
        rep movsd
3545 hidnplayr 940
  .nd:
941
 
3861 hidnplayr 942
        call    NET_packet_free
3704 hidnplayr 943
        pop     eax                                             ; return number of bytes copied to application
944
        xor     ebx, ebx
3545 hidnplayr 945
        ret
946
 
947
  .too_small:
3565 hidnplayr 948
        mov     eax, -1
3704 hidnplayr 949
        push    EMSGSIZE
950
        pop     ebx
3565 hidnplayr 951
        ret
3545 hidnplayr 952
 
3658 hidnplayr 953
  .wouldblock:
3704 hidnplayr 954
        push    EWOULDBLOCK
955
        pop     ebx
3658 hidnplayr 956
        ret
3545 hidnplayr 957
 
3658 hidnplayr 958
 
3704 hidnplayr 959
 
3545 hidnplayr 960
align 4
961
SOCKET_receive_local:
962
 
963
        ; does this socket have a PID yet?
964
        cmp     [eax + SOCKET.PID], 0
965
        jne     @f
966
 
967
        ; Change PID to that of current process
968
        mov     ebx, [TASK_BASE]
969
        mov     ebx, [ebx + TASKDATA.pid]
970
        mov     [eax + SOCKET.PID], ebx
3704 hidnplayr 971
        mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
3545 hidnplayr 972
      @@:
973
 
974
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
975
 
3704 hidnplayr 976
; ... continue to SOCKET_receive_stream
977
 
3545 hidnplayr 978
align 4
979
SOCKET_receive_stream:
980
 
3556 hidnplayr 981
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 982
 
3704 hidnplayr 983
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
984
        je      .wouldblock
985
 
986
        test    edi, MSG_PEEK
987
        jnz     .peek
988
 
3545 hidnplayr 989
        mov     ecx, esi
990
        mov     edi, edx
991
        xor     edx, edx
992
 
993
        add     eax, STREAM_SOCKET.rcv
3704 hidnplayr 994
        call    SOCKET_ring_read                                ; copy data from kernel buffer to application buffer
995
        call    SOCKET_ring_free                                ; free read memory
3545 hidnplayr 996
 
3704 hidnplayr 997
        mov     eax, ecx                                        ; return number of bytes copied
998
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
3545 hidnplayr 999
        ret
1000
 
3704 hidnplayr 1001
  .wouldblock:
1002
        push    EWOULDBLOCK
1003
        pop     ebx
1004
        ret
1005
 
3545 hidnplayr 1006
  .peek:
3565 hidnplayr 1007
        mov     eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3704 hidnplayr 1008
        xor     ebx, ebx
3545 hidnplayr 1009
        ret
1010
 
1011
 
1012
;-----------------------------------------------------------------
1013
;
1014
; SOCKET_send
1015
;
1016
;
1017
;  IN:  socket number in ecx
1018
;       pointer to data in edx
1019
;       datalength in esi
1020
;       flags in edi
1021
;  OUT: -1 on error
1022
;
1023
;-----------------------------------------------------------------
1024
align 4
1025
SOCKET_send:
1026
 
3556 hidnplayr 1027
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 1028
 
1029
        call    SOCKET_num_to_ptr
3658 hidnplayr 1030
        jz      .invalid
3545 hidnplayr 1031
 
1032
        mov     ecx, esi
1033
        mov     esi, edx
1034
 
1035
        jmp     [eax + SOCKET.snd_proc]
1036
 
3658 hidnplayr 1037
  .invalid:
3673 hidnplayr 1038
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1039
        mov     dword[esp+32], -1
1040
        ret
3545 hidnplayr 1041
 
3658 hidnplayr 1042
 
3545 hidnplayr 1043
align 4
1044
SOCKET_send_udp:
1045
 
3556 hidnplayr 1046
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 1047
 
1048
        mov     [esp+32], ecx
1049
        call    UDP_output
1050
        cmp     eax, -1
3658 hidnplayr 1051
        je      .error
3545 hidnplayr 1052
        ret
1053
 
3658 hidnplayr 1054
  .error:
1055
        mov     dword[esp+32], -1
3673 hidnplayr 1056
        mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
3658 hidnplayr 1057
        ret
3545 hidnplayr 1058
 
3658 hidnplayr 1059
 
3545 hidnplayr 1060
align 4
1061
SOCKET_send_tcp:
1062
 
3556 hidnplayr 1063
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 1064
 
1065
        push    eax
1066
        add     eax, STREAM_SOCKET.snd
1067
        call    SOCKET_ring_write
1068
        pop     eax
1069
 
1070
        mov     [esp+32], ecx
3658 hidnplayr 1071
        mov     [eax + SOCKET.errorcode], 0
1072
        push    eax
1073
        call    TCP_output              ; FIXME: this doesnt look pretty, does it?
1074
        pop     eax
1075
        mov     eax, [eax + SOCKET.errorcode]
3673 hidnplayr 1076
        mov     [esp+20], eax
3545 hidnplayr 1077
        ret
1078
 
1079
 
1080
align 4
1081
SOCKET_send_ip:
1082
 
3556 hidnplayr 1083
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 1084
 
1085
        mov     [esp+32], ecx
3658 hidnplayr 1086
        call    IPv4_output_raw         ; FIXME: IPv4_output_raw should return error codes!
3545 hidnplayr 1087
        cmp     eax, -1
3658 hidnplayr 1088
        je      .error
3545 hidnplayr 1089
        ret
1090
 
3658 hidnplayr 1091
  .error:
1092
        mov     dword[esp+32], -1
3673 hidnplayr 1093
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1094
        ret
3545 hidnplayr 1095
 
3658 hidnplayr 1096
 
3545 hidnplayr 1097
align 4
1098
SOCKET_send_icmp:
1099
 
3556 hidnplayr 1100
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 1101
 
1102
        mov     [esp+32], ecx
3658 hidnplayr 1103
        call    ICMP_output_raw         ; FIXME: errorcodes
3545 hidnplayr 1104
        cmp     eax, -1
3658 hidnplayr 1105
        je      .error
3545 hidnplayr 1106
        ret
1107
 
3658 hidnplayr 1108
  .error:
1109
        mov     dword[esp+32], -1
3673 hidnplayr 1110
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1111
        ret
3545 hidnplayr 1112
 
3658 hidnplayr 1113
 
3545 hidnplayr 1114
align 4
1115
SOCKET_send_pppoe:
1116
 
3556 hidnplayr 1117
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3545 hidnplayr 1118
 
1119
        mov     [esp+32], ecx
1120
        mov     ebx, [eax + SOCKET.device]
1121
 
3658 hidnplayr 1122
        call    PPPoE_discovery_output  ; FIXME: errorcodes
3545 hidnplayr 1123
        cmp     eax, -1
3658 hidnplayr 1124
        je      .error
3545 hidnplayr 1125
        ret
1126
 
3658 hidnplayr 1127
  .error:
1128
        mov     dword[esp+32], -1
3673 hidnplayr 1129
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1130
        ret
3545 hidnplayr 1131
 
1132
 
3658 hidnplayr 1133
 
3545 hidnplayr 1134
align 4
1135
SOCKET_send_local:
1136
 
1137
        ; does this socket have a PID yet?
1138
        cmp     [eax + SOCKET.PID], 0
1139
        jne     @f
1140
 
1141
        ; Change PID to that of current process
1142
        mov     ebx, [TASK_BASE]
1143
        mov     ebx, [ebx + TASKDATA.pid]
1144
        mov     [eax + SOCKET.PID], ebx
1145
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1146
      @@:
1147
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
1148
 
1149
align 4
1150
SOCKET_send_local_:
1151
 
3556 hidnplayr 1152
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1153
 
1154
        ; get the other side's socket and check if it still exists
1155
        mov     eax, [eax + SOCKET.device]
1156
        call    SOCKET_check
3658 hidnplayr 1157
        jz      .invalid
3545 hidnplayr 1158
 
1159
        ; allright, shove in the data!
1160
        push    eax
1161
        add     eax, STREAM_SOCKET.rcv
1162
        call    SOCKET_ring_write
1163
        pop     eax
1164
 
1165
        ; return the number of written bytes (or errorcode) to application
1166
        mov     [esp+32], ecx
1167
 
1168
        ; and notify the other end
1169
        call    SOCKET_notify
1170
 
1171
        ret
1172
 
3658 hidnplayr 1173
  .invalid:
1174
        mov     dword[esp+32], -1
3673 hidnplayr 1175
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1176
        ret
3545 hidnplayr 1177
 
3658 hidnplayr 1178
 
3545 hidnplayr 1179
;-----------------------------------------------------------------
1180
;
1181
; SOCKET_get_options
1182
;
1183
;  IN:  ecx = socket number
1184
;       edx = pointer to the options:
1185
;               dd      level, optname, optval, optlen
1186
;  OUT: -1 on error
1187
;
1188
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
1189
; TODO: find best way to notify that send()'ed data were acknowledged
1190
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1191
;
1192
;-----------------------------------------------------------------
1193
align 4
1194
SOCKET_get_opt:
1195
 
3556 hidnplayr 1196
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1197
 
1198
        call    SOCKET_num_to_ptr
3658 hidnplayr 1199
        jz      .invalid
3545 hidnplayr 1200
 
1201
        cmp     dword [edx], IP_PROTO_TCP
3658 hidnplayr 1202
        jne     .invalid
3545 hidnplayr 1203
        cmp     dword [edx+4], -2
1204
        je      @f
1205
        cmp     dword [edx+4], -3
3658 hidnplayr 1206
        jne     .invalid
3545 hidnplayr 1207
@@:
1208
;        mov     eax, [edx+12]
1209
;        test    eax, eax
1210
;        jz      .fail
1211
;        cmp     dword [eax], 4
1212
;        mov     dword [eax], 4
1213
;        jb      .fail
1214
;        stdcall net_socket_num_to_addr, ecx
1215
;        test    eax, eax
1216
;        jz      .fail
1217
;        ; todo: check that eax is really TCP socket
1218
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
1219
;        cmp     dword [edx+4], -2
1220
;        jz      @f
1221
;        mov     ecx, [eax + TCP_SOCKET.state]
1222
@@:
1223
        mov     eax, [edx+8]
1224
        test    eax, eax
1225
        jz      @f
1226
        mov     [eax], ecx
1227
@@:
1228
        mov     dword [esp+32], 0
1229
        ret
1230
 
3658 hidnplayr 1231
  .invalid:
1232
        mov     dword[esp+32], -1
3673 hidnplayr 1233
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1234
        ret
3545 hidnplayr 1235
 
1236
 
3658 hidnplayr 1237
 
3545 hidnplayr 1238
;-----------------------------------------------------------------
1239
;
1240
; SOCKET_set_options
1241
;
1242
;  IN:  ecx = socket number
1243
;       edx = pointer to the options:
1244
;               dd      level, optname, optlen, optval
1245
;  OUT: -1 on error
1246
;
1247
;-----------------------------------------------------------------
1248
align 4
1249
SOCKET_set_opt:
1250
 
3556 hidnplayr 1251
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1252
 
1253
        call    SOCKET_num_to_ptr
3658 hidnplayr 1254
        jz      .invalid
3545 hidnplayr 1255
 
1256
        cmp     dword [edx], SOL_SOCKET
3658 hidnplayr 1257
        jne     .invalid
3545 hidnplayr 1258
 
1259
        cmp     dword [edx+4], SO_BINDTODEVICE
1260
        je      .bind
1261
 
3658 hidnplayr 1262
  .invalid:
1263
        mov     dword[esp+32], -1
3673 hidnplayr 1264
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1265
        ret
3545 hidnplayr 1266
 
1267
  .bind:
3658 hidnplayr 1268
        cmp     dword[edx+8], 0
3545 hidnplayr 1269
        je      .unbind
1270
 
3658 hidnplayr 1271
        movzx   edx, byte[edx + 9]
3600 hidnplayr 1272
        cmp     edx, NET_DEVICES_MAX
3658 hidnplayr 1273
        ja      .invalid
3545 hidnplayr 1274
 
1275
        mov     edx, [NET_DRV_LIST + 4*edx]
1276
        test    edx, edx
3658 hidnplayr 1277
        jz      .already
3545 hidnplayr 1278
        mov     [eax + SOCKET.device], edx
1279
 
3556 hidnplayr 1280
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
3545 hidnplayr 1281
 
3658 hidnplayr 1282
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1283
        ret
1284
 
1285
  .unbind:
1286
        mov     [eax + SOCKET.device], 0
1287
 
3658 hidnplayr 1288
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1289
        ret
1290
 
3658 hidnplayr 1291
  .already:
3673 hidnplayr 1292
        mov     dword[esp+20], EALREADY
3658 hidnplayr 1293
        mov     dword[esp+32], -1
1294
        ret
3545 hidnplayr 1295
 
1296
 
3658 hidnplayr 1297
 
1298
 
3545 hidnplayr 1299
;-----------------------------------------------------------------
1300
;
1301
; SOCKET_pair
1302
;
1303
; Allocates a pair of linked LOCAL domain sockets
1304
;
1305
; IN: /
1306
; OUT: eax is socket1 num, -1 on error
1307
;      ebx is socket2 num
1308
;
1309
;-----------------------------------------------------------------
1310
align 4
1311
SOCKET_pair:
1312
 
3556 hidnplayr 1313
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1314
 
1315
        call    SOCKET_alloc
3658 hidnplayr 1316
        jz      .nomem1
3545 hidnplayr 1317
        mov     [esp+32], edi   ; application's eax
1318
 
1319
        mov     [eax + SOCKET.Domain], AF_LOCAL
1320
        mov     [eax + SOCKET.Type], SOCK_STREAM
1321
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1322
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1323
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1324
        mov     [eax + SOCKET.PID], 0
1325
        mov     ebx, eax
1326
 
1327
        call    SOCKET_alloc
3658 hidnplayr 1328
        jz      .nomem2
3673 hidnplayr 1329
        mov     [esp+20], edi   ; application's ebx
3545 hidnplayr 1330
 
1331
        mov     [eax + SOCKET.Domain], AF_LOCAL
1332
        mov     [eax + SOCKET.Type], SOCK_STREAM
1333
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1334
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1335
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1336
        mov     [eax + SOCKET.PID], 0
1337
 
1338
        ; Link the two sockets to eachother
1339
        mov     [eax + SOCKET.device], ebx
1340
        mov     [ebx + SOCKET.device], eax
1341
 
1342
        lea     eax, [eax + STREAM_SOCKET.rcv]
1343
        call    SOCKET_ring_create
1344
 
1345
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1346
        call    SOCKET_ring_create
1347
        pop     eax
1348
 
1349
        ret
1350
 
3658 hidnplayr 1351
  .nomem2:
3545 hidnplayr 1352
        mov     eax, ebx
1353
        call    SOCKET_free
3658 hidnplayr 1354
  .nomem1:
1355
        mov     dword[esp+32], -1
1356
        mov     dword[esp+28], ENOMEM
1357
        ret
3545 hidnplayr 1358
 
1359
 
1360
 
1361
;-----------------------------------------------------------------
1362
;
1363
; SOCKET_debug
1364
;
1365
;  Copies socket variables to application buffer
1366
;
1367
;  IN:  ecx = socket number
1368
;       edx = pointer to buffer
1369
;
1370
;  OUT: -1 on error
1371
;-----------------------------------------------------------------
1372
align 4
1373
SOCKET_debug:
1374
 
3556 hidnplayr 1375
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1376
 
1377
        mov     edi, edx
1378
 
1379
        test    ecx, ecx
1380
        jz      .returnall
1381
 
1382
        call    SOCKET_num_to_ptr
3658 hidnplayr 1383
        jz      .invalid
3545 hidnplayr 1384
 
1385
        mov     esi, eax
1386
        mov     ecx, SOCKETBUFFSIZE/4
3711 clevermous 1387
        rep movsd
3545 hidnplayr 1388
 
3658 hidnplayr 1389
        mov     dword[esp+32], 0
3545 hidnplayr 1390
        ret
1391
 
1392
  .returnall:
1393
        mov     ebx, net_sockets
1394
  .next_socket:
1395
        mov     ebx, [ebx + SOCKET.NextPtr]
1396
        test    ebx, ebx
1397
        jz      .done
1398
        mov     eax, [ebx + SOCKET.Number]
1399
        stosd
1400
        jmp     .next_socket
1401
  .done:
1402
        xor     eax, eax
1403
        stosd
3658 hidnplayr 1404
        mov     dword[esp+32], eax
1405
        ret
3545 hidnplayr 1406
 
3658 hidnplayr 1407
  .invalid:
1408
        mov     dword[esp+32], -1
1409
        mov     dword[esp+28], EINVAL
3545 hidnplayr 1410
        ret
1411
 
1412
 
1413
;-----------------------------------------------------------------
1414
;
1415
; SOCKET_find_port
1416
;
1417
; Fills in the local port number for TCP and UDP sockets
1418
; This procedure always works because the number of sockets is
1419
; limited to a smaller number then the number of possible ports
1420
;
1421
;  IN:  eax = socket pointer
1422
;  OUT: /
1423
;
1424
;-----------------------------------------------------------------
1425
align 4
1426
SOCKET_find_port:
1427
 
3556 hidnplayr 1428
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1429
 
1430
        push    ebx esi ecx
1431
 
1432
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1433
        je      .udp
1434
 
1435
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1436
        je      .tcp
1437
 
1438
        pop     ecx esi ebx
1439
        ret
1440
 
1441
  .udp:
1442
        mov     bx, [last_UDP_port]
1443
        call    .findit
1444
        mov     [last_UDP_port], bx
1445
 
1446
        pop     ecx esi ebx
1447
        ret
1448
 
1449
  .tcp:
1450
        mov     bx, [last_TCP_port]
1451
        call    .findit
1452
        mov     [last_TCP_port], bx
1453
 
1454
        pop     ecx esi ebx
1455
        ret
1456
 
1457
 
1458
  .restart:
1459
        mov     bx, MIN_EPHEMERAL_PORT_N
1460
  .findit:
1461
        cmp     bx, MAX_EPHEMERAL_PORT_N
1462
        je      .restart
1463
 
1464
        add     bh, 1
1465
        adc     bl, 0
1466
 
1467
        call    SOCKET_check_port
1468
        jz      .findit
1469
        ret
1470
 
1471
 
1472
 
1473
;-----------------------------------------------------------------
1474
;
1475
; SOCKET_check_port (to be used with AF_INET only!)
1476
;
1477
; Checks if a local port number is unused
1478
; If the proposed port number is unused, it is filled in in the socket structure
1479
;
1480
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
1481
;        bx = proposed socket number (network byte order)
1482
;
1483
;  OUT:  ZF = set on error
1484
;
1485
;-----------------------------------------------------------------
1486
align 4
1487
SOCKET_check_port:
1488
 
3556 hidnplayr 1489
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1490
 
3647 hidnplayr 1491
        pusha
1492
        mov     ecx, socket_mutex
1493
        call    mutex_lock
1494
        popa
1495
 
3545 hidnplayr 1496
        mov     ecx, [eax + SOCKET.Protocol]
1497
        mov     edx, [eax + IP_SOCKET.LocalIP]
1498
        mov     esi, net_sockets
1499
 
1500
  .next_socket:
1501
        mov     esi, [esi + SOCKET.NextPtr]
1502
        or      esi, esi
1503
        jz      .port_ok
1504
 
1505
        cmp     [esi + SOCKET.Protocol], ecx
1506
        jne     .next_socket
1507
 
1508
        cmp     [esi + IP_SOCKET.LocalIP], edx
1509
        jne     .next_socket
1510
 
1511
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1512
        jne     .next_socket
1513
 
3647 hidnplayr 1514
        pusha
1515
        mov     ecx, socket_mutex
1516
        call    mutex_unlock
1517
        popa
1518
 
3556 hidnplayr 1519
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1520
        ret
1521
 
1522
  .port_ok:
3647 hidnplayr 1523
        pusha
1524
        mov     ecx, socket_mutex
1525
        call    mutex_unlock
1526
        popa
1527
 
3556 hidnplayr 1528
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1529
        mov     [eax + UDP_SOCKET.LocalPort], bx
1530
        or      bx, bx                                  ; clear the zero-flag
1531
        ret
1532
 
1533
 
1534
 
1535
;-----------------------------------------------------------------
1536
;
1537
; SOCKET_input
1538
;
1539
; Updates a (stateless) socket with received data
1540
;
1541
; Note: the mutex should already be set !
1542
;
1543
;  IN:  eax = socket ptr
1544
;       ecx = data size
1545
;       esi = ptr to data
1546
;       [esp] = ptr to buf
1547
;       [esp + 4] = buf size
1548
;
1549
;  OUT: /
1550
;
1551
;-----------------------------------------------------------------
1552
align 4
1553
SOCKET_input:
1554
 
3556 hidnplayr 1555
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1556
 
1557
        mov     [esp+4], ecx
1558
        push    esi
1559
        mov     esi, esp
1560
 
1561
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1562
 
3556 hidnplayr 1563
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1564
        add     esp, sizeof.socket_queue_entry
1565
 
1566
        pusha
1567
        lea     ecx, [eax + SOCKET.mutex]
1568
        call    mutex_unlock
1569
        popa
1570
 
1571
        jmp     SOCKET_notify
1572
 
1573
  .full:
3556 hidnplayr 1574
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1575
 
1576
        pusha
1577
        lea     ecx, [eax + SOCKET.mutex]
1578
        call    mutex_unlock
1579
        popa
1580
 
3861 hidnplayr 1581
        call    NET_packet_free
3545 hidnplayr 1582
        add     esp, 8
1583
 
1584
        ret
1585
 
1586
 
1587
;--------------------------
1588
;
1589
; eax = ptr to ring struct (just a buffer of the right size)
1590
;
1591
align 4
1592
SOCKET_ring_create:
1593
 
1594
        push    esi
1595
        mov     esi, eax
1596
 
1597
        push    edx
1598
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1599
        pop     edx
1600
 
3556 hidnplayr 1601
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
3545 hidnplayr 1602
 
1603
        pusha
1604
        lea     ecx, [esi + RING_BUFFER.mutex]
1605
        call    mutex_init
1606
        popa
1607
 
1608
        mov     [esi + RING_BUFFER.start_ptr], eax
1609
        mov     [esi + RING_BUFFER.write_ptr], eax
1610
        mov     [esi + RING_BUFFER.read_ptr], eax
1611
        mov     [esi + RING_BUFFER.size], 0
1612
        add     eax, SOCKET_MAXDATA
1613
        mov     [esi + RING_BUFFER.end_ptr], eax
1614
        mov     eax, esi
1615
        pop     esi
1616
 
1617
        ret
1618
 
1619
;-----------------------------------------------------------------
1620
;
1621
; SOCKET_ring_write
1622
;
1623
; Adds data to a stream socket, and updates write pointer and size
1624
;
1625
;  IN:  eax = ptr to ring struct
1626
;       ecx = data size
1627
;       esi = ptr to data
1628
;
1629
;  OUT: ecx = number of bytes stored
1630
;
1631
;-----------------------------------------------------------------
1632
align 4
1633
SOCKET_ring_write:
1634
 
3556 hidnplayr 1635
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1636
 
1637
; lock mutex
1638
        pusha
1639
        lea     ecx, [eax + RING_BUFFER.mutex]
1640
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1641
        popa
1642
 
1643
; calculate available size
1644
        mov     edi, SOCKET_MAXDATA
1645
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
1646
        cmp     ecx, edi
1647
        jbe     .copy
1648
        mov     ecx, edi
1649
  .copy:
1650
        mov     edi, [eax + RING_BUFFER.write_ptr]
3556 hidnplayr 1651
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1652
 
1653
; update write ptr
1654
        push    edi
1655
        add     edi, ecx
1656
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1657
        jb      @f
1658
        sub     edi, SOCKET_MAXDATA                             ; WRAP
1659
  @@:
1660
        mov     [eax + RING_BUFFER.write_ptr], edi
1661
        pop     edi
1662
 
1663
; update size
1664
        add     [eax + RING_BUFFER.size], ecx
1665
 
1666
; copy the data
1667
        push    ecx
1668
        shr     ecx, 1
1669
        jnc     .nb
1670
        movsb
1671
  .nb:
1672
        shr     ecx, 1
1673
        jnc     .nw
1674
        movsw
1675
  .nw:
1676
        test    ecx, ecx
1677
        jz      .nd
3711 clevermous 1678
        rep movsd
3545 hidnplayr 1679
  .nd:
1680
        pop     ecx
1681
 
1682
; unlock mutex
1683
        push    eax ecx
1684
        lea     ecx, [eax + RING_BUFFER.mutex]
1685
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1686
        pop     ecx eax
1687
 
1688
        ret
1689
 
1690
;-----------------------------------------------------------------
1691
;
1692
; SOCKET_ring_read
1693
;
1694
;  IN:  eax = ring struct ptr
1695
;       ecx = bytes to read
1696
;       edx = offset
1697
;       edi = ptr to buffer start
1698
;
1699
;  OUT: eax = unchanged
1700
;       ecx = number of bytes read (0 on error)
1701
;       edx = destroyed
1702
;       esi = destroyed
1703
;       edi = ptr to buffer end
1704
;
1705
;-----------------------------------------------------------------
1706
align 4
1707
SOCKET_ring_read:
1708
 
3556 hidnplayr 1709
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1710
 
1711
        pusha
1712
        lea     ecx, [eax + RING_BUFFER.mutex]
1713
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1714
        popa
1715
 
1716
        mov     esi, [eax + RING_BUFFER.read_ptr]
1717
        add     esi, edx                                        ; esi = start_ptr + offset
1718
 
1719
        neg     edx
1720
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1721
        jle     .no_data_at_all
1722
 
1723
        pusha
1724
        lea     ecx, [eax + RING_BUFFER.mutex]
1725
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1726
        popa
1727
 
1728
        cmp     ecx, edx
1729
        ja      .less_data
1730
 
1731
  .copy:
3556 hidnplayr 1732
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1733
        push    ecx
1734
        shr     ecx, 1
1735
        jnc     .nb
1736
        movsb
1737
  .nb:
1738
        shr     ecx, 1
1739
        jnc     .nw
1740
        movsw
1741
  .nw:
1742
        test    ecx, ecx
1743
        jz      .nd
3711 clevermous 1744
        rep movsd
3545 hidnplayr 1745
  .nd:
1746
        pop     ecx
1747
        ret
1748
 
1749
  .no_data_at_all:
1750
        pusha
1751
        lea     ecx, [eax + RING_BUFFER.mutex]
1752
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1753
        popa
1754
 
3556 hidnplayr 1755
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1756
        xor     ecx, ecx
1757
        ret
1758
 
1759
  .less_data:
1760
        mov     ecx, edx
1761
        jmp     .copy
1762
 
1763
 
1764
;-----------------------------------------------------------------
1765
;
1766
; SOCKET_ring_free
1767
;
1768
; Free's some bytes from the ringbuffer
1769
;
1770
;  IN:  eax = ptr to ring struct
1771
;       ecx = data size
1772
;
1773
;  OUT: ecx = number of bytes free-ed
1774
;
1775
;-----------------------------------------------------------------
1776
align 4
1777
SOCKET_ring_free:
1778
 
3556 hidnplayr 1779
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 1780
 
1781
        push    eax ecx
1782
        lea     ecx, [eax + RING_BUFFER.mutex]
1783
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1784
        pop     ecx eax
1785
 
1786
        sub     [eax + RING_BUFFER.size], ecx
1787
        jb      .error
1788
        add     [eax + RING_BUFFER.read_ptr], ecx
1789
 
1790
        mov     edx, [eax + RING_BUFFER.end_ptr]
1791
        cmp     [eax + RING_BUFFER.read_ptr], edx
1792
        jb      @f
1793
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1794
       @@:
1795
 
1796
        push    eax ecx
1797
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1798
        call    mutex_unlock
1799
        pop     ecx eax
1800
 
1801
        ret
1802
 
1803
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
3556 hidnplayr 1804
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1805
        add     [eax + RING_BUFFER.size], ecx
1806
 
1807
        push    eax
1808
        lea     ecx, [eax + RING_BUFFER.mutex]
1809
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1810
        pop     eax
1811
 
1812
        xor     ecx, ecx
1813
        ret
1814
 
1815
 
1816
;-----------------------------------------------------------------
1817
;
1818
; SOCKET_block
1819
;
1820
; Suspends the thread attached to a socket
1821
;
1822
;  IN:  eax = socket ptr
3674 hidnplayr 1823
;  OUT: eax = unchanged
3545 hidnplayr 1824
;
1825
;-----------------------------------------------------------------
1826
align 4
1827
SOCKET_block:
1828
 
3556 hidnplayr 1829
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1830
 
1831
        pushf
3674 hidnplayr 1832
        push    eax
3545 hidnplayr 1833
        cli
1834
 
1835
        ; Set the 'socket is blocked' flag
1836
        or      [eax + SOCKET.state], SS_BLOCKED
1837
 
1838
        ; Suspend the thread
1839
        push    edx
1840
        mov     edx, [TASK_BASE]
1841
        mov     [edx + TASKDATA.state], 1               ; Suspended
1842
 
1843
        ; Remember the thread ID so we can wake it up again
1844
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1845
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1846
        mov     [eax + SOCKET.TID], edx
1847
        pop     edx
1848
 
1849
        call    change_task
3674 hidnplayr 1850
        pop     eax
3545 hidnplayr 1851
        popf
1852
 
3556 hidnplayr 1853
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
3545 hidnplayr 1854
 
1855
        ret
1856
 
1857
 
1858
;-----------------------------------------------------------------
1859
;
1860
; SOCKET_notify
1861
;
1862
; notify's the owner of a socket that something happened
1863
;
1864
;  IN:  eax = socket ptr
3674 hidnplayr 1865
;  OUT: eax = unchanged
3545 hidnplayr 1866
;
1867
;-----------------------------------------------------------------
1868
align 4
1869
SOCKET_notify:
1870
 
3556 hidnplayr 1871
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1872
 
1873
        call    SOCKET_check
1874
        jz      .error
1875
 
1876
        test    [eax + SOCKET.state], SS_BLOCKED
1877
        jnz     .unblock
1878
 
3704 hidnplayr 1879
;        test    [eax + SOCKET.options], SO_NONBLOCK
1880
;        jz      .error
3545 hidnplayr 1881
 
1882
        push    eax ecx esi
1883
 
1884
; socket exists and is of non blocking type.
1885
; We'll try to flag an event to the thread
1886
 
1887
        mov     eax, [eax + SOCKET.TID]
1888
        test    eax, eax
1889
        jz      .done
1890
        mov     ecx, 1
1891
        mov     esi, TASK_DATA + TASKDATA.pid
1892
 
1893
  .next_pid:
1894
        cmp     [esi], eax
1895
        je      .found_pid
1896
        inc     ecx
1897
        add     esi, 0x20
1898
        cmp     ecx, [TASK_COUNT]
1899
        jbe     .next_pid
1900
; PID not found, TODO: close socket!
1901
        jmp     .done
1902
 
1903
  .found_pid:
1904
        shl     ecx, 8
1905
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1906
 
3817 hidnplayr 1907
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", eax
3545 hidnplayr 1908
        jmp     .done
1909
 
1910
  .unblock:
1911
        push    eax ecx esi
1912
        ; Clear the 'socket is blocked' flag
1913
        and     [eax + SOCKET.state], not SS_BLOCKED
1914
 
1915
        ; Find the thread's TASK_DATA
1916
        mov     eax, [eax + SOCKET.TID]
1917
        test    eax, eax
1918
        jz      .error
1919
        xor     ecx, ecx
1920
        inc     ecx
1921
        mov     esi, TASK_DATA
1922
  .next:
1923
        cmp     [esi + TASKDATA.pid], eax
1924
        je      .found
1925
        inc     ecx
1926
        add     esi, 0x20
1927
        cmp     ecx, [TASK_COUNT]
1928
        jbe     .next
1929
        jmp     .error
1930
  .found:
1931
 
1932
        ; Run the thread
1933
        mov     [esi + TASKDATA.state], 0       ; Running
3556 hidnplayr 1934
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
3545 hidnplayr 1935
 
1936
  .done:
1937
        pop     esi ecx eax
1938
 
1939
  .error:
1940
        ret
1941
 
1942
 
1943
;--------------------------------------------------------------------
1944
;
1945
; SOCKET_alloc
1946
;
1947
; Allocate memory for socket data and put new socket into the list
1948
; Newly created socket is initialized with calling PID and number and
1949
; put into beginning of list (which is a fastest way).
1950
;
1951
; IN:  /
1952
; OUT: eax = 0 on error, socket ptr otherwise
1953
;      edi = socket number
1954
;       ZF = cleared on error
1955
;
1956
;--------------------------------------------------------------------
1957
align 4
1958
SOCKET_alloc:
1959
 
1960
        push    ebx
1961
 
1962
        stdcall kernel_alloc, SOCKETBUFFSIZE
3556 hidnplayr 1963
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1964
        or      eax, eax
1965
        jz      .exit
1966
 
1967
; zero-initialize allocated memory
1968
        push    eax
1969
        mov     edi, eax
1970
        mov     ecx, SOCKETBUFFSIZE / 4
1971
        xor     eax, eax
3711 clevermous 1972
        rep stosd
3545 hidnplayr 1973
        pop     eax
1974
 
1975
; set send-and receive procedures to return -1
3658 hidnplayr 1976
        mov     [eax + SOCKET.snd_proc], .not_yet
1977
        mov     [eax + SOCKET.rcv_proc], .not_yet
3545 hidnplayr 1978
 
3647 hidnplayr 1979
        pusha
1980
        mov     ecx, socket_mutex
1981
        call    mutex_lock
1982
        popa
1983
 
3545 hidnplayr 1984
; find first free socket number and use it
1985
        mov     edi, [last_socket_num]
1986
  .next_socket_number:
1987
        inc     edi
1988
        jz      .next_socket_number     ; avoid socket nr 0
1989
        cmp     edi, -1
1990
        je      .next_socket_number     ; avoid socket nr -1
1991
        mov     ebx, net_sockets
1992
  .next_socket:
1993
        mov     ebx, [ebx + SOCKET.NextPtr]
1994
        test    ebx, ebx
1995
        jz      .last_socket
1996
 
1997
        cmp     [ebx + SOCKET.Number], edi
1998
        jne     .next_socket
1999
        jmp     .next_socket_number
2000
 
2001
  .last_socket:
2002
        mov     [last_socket_num], edi
2003
        mov     [eax + SOCKET.Number], edi
3556 hidnplayr 2004
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 2005
 
2006
; Fill in PID
2007
        mov     ebx, [TASK_BASE]
2008
        mov     ebx, [ebx + TASKDATA.pid]
2009
        mov     [eax + SOCKET.PID], ebx
2010
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
2011
 
2012
; init mutex
2013
        pusha
2014
        lea     ecx, [eax + SOCKET.mutex]
2015
        call    mutex_init
2016
        popa
2017
 
2018
; add socket to the list by re-arranging some pointers
2019
        mov     ebx, [net_sockets + SOCKET.NextPtr]
2020
 
2021
        mov     [eax + SOCKET.PrevPtr], net_sockets
2022
        mov     [eax + SOCKET.NextPtr], ebx
2023
 
2024
        test    ebx, ebx
2025
        jz      @f
2026
 
2027
        pusha
2028
        lea     ecx, [ebx + SOCKET.mutex]
2029
        call    mutex_lock
2030
        popa
2031
 
2032
        mov     [ebx + SOCKET.PrevPtr], eax
2033
 
2034
        pusha
2035
        lea     ecx, [ebx + SOCKET.mutex]
2036
        call    mutex_unlock
2037
        popa
2038
       @@:
2039
 
2040
        mov     [net_sockets + SOCKET.NextPtr], eax
2041
        or      eax, eax                ; used to clear zero flag
3647 hidnplayr 2042
 
2043
        pusha
2044
        mov     ecx, socket_mutex
2045
        call    mutex_unlock
2046
        popa
2047
 
3545 hidnplayr 2048
  .exit:
2049
        pop     ebx
2050
 
2051
        ret
2052
 
3658 hidnplayr 2053
  .not_yet:
3673 hidnplayr 2054
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2055
        mov     dword[esp+32], -1
2056
        ret
3545 hidnplayr 2057
 
3658 hidnplayr 2058
 
3545 hidnplayr 2059
;----------------------------------------------------
2060
;
2061
; SOCKET_free
2062
;
2063
; Free socket data memory and remove socket from the list
3884 hidnplayr 2064
; Caller should lock and unlock socket_mutex
3545 hidnplayr 2065
;
2066
; IN:  eax = socket ptr
2067
; OUT: /
2068
;
2069
;----------------------------------------------------
2070
align 4
2071
SOCKET_free:
2072
 
3556 hidnplayr 2073
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 2074
 
2075
        call    SOCKET_check
2076
        jz      .error
2077
 
2078
        push    ebx
2079
 
2080
        pusha
2081
        lea     ecx, [eax + SOCKET.mutex]
2082
        call    mutex_lock
2083
        popa
2084
 
2085
        cmp     [eax + SOCKET.Domain], AF_INET4
2086
        jnz     .no_tcp
2087
 
2088
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2089
        jnz     .no_tcp
2090
 
2091
        mov     ebx, eax
2092
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
2093
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
2094
        mov     eax, ebx
2095
  .no_tcp:
2096
 
3652 hidnplayr 2097
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 2098
        push    eax                             ; this will be passed to kernel_free
2099
        mov     ebx, [eax + SOCKET.NextPtr]
2100
        mov     eax, [eax + SOCKET.PrevPtr]
2101
 
3556 hidnplayr 2102
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 2103
 
2104
        test    eax, eax
2105
        jz      @f
2106
        mov     [eax + SOCKET.NextPtr], ebx
2107
       @@:
2108
 
2109
        test    ebx, ebx
2110
        jz      @f
2111
        mov     [ebx + SOCKET.PrevPtr], eax
2112
       @@:
2113
 
2114
        call    kernel_free
2115
        pop     ebx
2116
 
3652 hidnplayr 2117
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
2118
 
2119
  .error:
3545 hidnplayr 2120
        ret
2121
 
2122
;------------------------------------
2123
;
2124
; SOCKET_fork
2125
;
2126
; Create a child socket
2127
;
2128
; IN:  socket nr in ebx
2129
; OUT: child socket nr in eax
2130
;
2131
;-----------------------------------
2132
align 4
2133
SOCKET_fork:
2134
 
3556 hidnplayr 2135
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 2136
 
2137
; Exit if backlog queue is full
2138
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
2139
        cmp     ax, [ebx + SOCKET.backlog]
2140
        jae     .fail
2141
 
2142
; Allocate new socket
2143
        push    ebx
2144
        call    SOCKET_alloc
2145
        pop     ebx
2146
        jz      .fail
2147
 
2148
        push    eax
2149
        mov     esi, esp
2150
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
2151
        pop     eax
2152
 
2153
; Copy structure from current socket to new
3817 hidnplayr 2154
; We start at PID to preserve the socket num, 2 pointers and mutex
2155
; TID will be filled in later
3545 hidnplayr 2156
        lea     esi, [ebx + SOCKET.PID]
2157
        lea     edi, [eax + SOCKET.PID]
2158
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
3711 clevermous 2159
        rep movsd
3545 hidnplayr 2160
 
2161
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2162
 
3817 hidnplayr 2163
; Notify owner of parent socket
2164
        push    eax
2165
        mov     eax, ebx
2166
        call    SOCKET_notify
2167
        pop     eax
2168
 
3545 hidnplayr 2169
        ret
2170
 
2171
  .fail2:
2172
        add     esp, 4+4+4
2173
  .fail:
3556 hidnplayr 2174
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 2175
        xor     eax, eax
2176
        ret
2177
 
2178
 
2179
;---------------------------------------------------
2180
;
2181
; SOCKET_num_to_ptr
2182
;
2183
; Get socket structure address by its number
2184
;
2185
; IN:  ecx = socket number
2186
; OUT: eax = 0 on error, socket ptr otherwise
2187
;       ZF = set on error
2188
;
2189
;---------------------------------------------------
2190
align 4
2191
SOCKET_num_to_ptr:
2192
 
3556 hidnplayr 2193
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2194
 
3647 hidnplayr 2195
        pusha
2196
        mov     ecx, socket_mutex
2197
        call    mutex_lock
2198
        popa
2199
 
3545 hidnplayr 2200
        mov     eax, net_sockets
2201
 
2202
  .next_socket:
2203
        mov     eax, [eax + SOCKET.NextPtr]
2204
        or      eax, eax
2205
        jz      .error
2206
        cmp     [eax + SOCKET.Number], ecx
2207
        jne     .next_socket
2208
 
2209
        test    eax, eax
2210
 
3647 hidnplayr 2211
        pusha
2212
        mov     ecx, socket_mutex
2213
        call    mutex_unlock
2214
        popa
2215
 
3556 hidnplayr 2216
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2217
        ret
2218
 
2219
  .error:
3647 hidnplayr 2220
        pusha
2221
        mov     ecx, socket_mutex
2222
        call    mutex_unlock
2223
        popa
2224
 
3637 hidnplayr 2225
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax
3545 hidnplayr 2226
        ret
2227
 
2228
 
2229
;---------------------------------------------------
2230
;
2231
; SOCKET_ptr_to_num
2232
;
2233
; Get socket number by its address
2234
;
2235
; IN:  eax = socket ptr
2236
; OUT: eax = 0 on error, socket num otherwise
2237
;       ZF = set on error
2238
;
2239
;---------------------------------------------------
2240
align 4
2241
SOCKET_ptr_to_num:
2242
 
3556 hidnplayr 2243
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2244
 
2245
        call    SOCKET_check
2246
        jz      .error
2247
 
2248
        mov     eax, [eax + SOCKET.Number]
2249
 
3556 hidnplayr 2250
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2251
        ret
2252
 
2253
  .error:
3556 hidnplayr 2254
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2255
        ret
2256
 
2257
 
2258
;---------------------------------------------------
2259
;
2260
; SOCKET_check
2261
;
2262
; checks if the given value is really a socket ptr
2263
;
2264
; IN:  eax = socket ptr
2265
; OUT: eax = 0 on error, unchanged otherwise
2266
;       ZF = set on error
2267
;
2268
;---------------------------------------------------
2269
align 4
2270
SOCKET_check:
2271
 
3556 hidnplayr 2272
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2273
 
2274
        push    ebx
2275
        mov     ebx, net_sockets
2276
 
2277
  .next_socket:
2278
        mov     ebx, [ebx + SOCKET.NextPtr]
2279
        or      ebx, ebx
2280
        jz      .done
2281
        cmp     ebx, eax
2282
        jnz     .next_socket
2283
 
2284
  .done:
2285
        mov     eax, ebx
2286
        test    eax, eax
2287
        pop     ebx
2288
 
2289
        ret
2290
 
2291
 
2292
 
2293
;---------------------------------------------------
2294
;
2295
; SOCKET_check_owner
2296
;
2297
; checks if the caller application owns the socket
2298
;
2299
; IN:  eax = socket ptr
2300
; OUT:  ZF = true/false
2301
;
2302
;---------------------------------------------------
2303
align 4
2304
SOCKET_check_owner:
2305
 
3556 hidnplayr 2306
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2307
 
2308
        push    ebx
2309
        mov     ebx, [TASK_BASE]
2310
        mov     ebx, [ebx + TASKDATA.pid]
2311
        cmp     [eax + SOCKET.PID], ebx
3711 clevermous 2312
        pop     ebx
3545 hidnplayr 2313
 
2314
        ret
2315
 
2316
 
2317
 
2318
 
2319
;------------------------------------------------------
2320
;
2321
; SOCKET_process_end
2322
;
2323
; Kernel calls this function when a certain process ends
2324
; This function will check if the process had any open sockets
2325
; And update them accordingly
2326
;
2327
; IN:  edx = pid
2328
; OUT: /
2329
;
2330
;------------------------------------------------------
2331
align 4
2332
SOCKET_process_end:
2333
 
3556 hidnplayr 2334
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2335
 
3647 hidnplayr 2336
        pusha
2337
        mov     ecx, socket_mutex
2338
        call    mutex_lock
2339
        popa
2340
 
3545 hidnplayr 2341
        push    ebx
2342
        mov     ebx, net_sockets
2343
 
2344
  .next_socket:
2345
        mov     ebx, [ebx + SOCKET.NextPtr]
2346
  .next_socket_test:
2347
        test    ebx, ebx
2348
        jz      .done
2349
 
2350
        cmp     [ebx + SOCKET.PID], edx
2351
        jne     .next_socket
2352
 
3556 hidnplayr 2353
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2354
 
2355
        mov     [ebx + SOCKET.PID], 0
2356
        mov     eax, ebx
2357
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2358
 
3545 hidnplayr 2359
        pusha
3652 hidnplayr 2360
        cmp     [eax + SOCKET.Domain], AF_INET4
2361
        jne     .free
2362
 
2363
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2364
        jne     .free
2365
 
2366
        call    TCP_close
2367
        jmp     .closed
2368
 
2369
  .free:
2370
        call    SOCKET_free
2371
 
2372
  .closed:
3545 hidnplayr 2373
        popa
2374
        jmp     .next_socket_test
2375
 
2376
  .done:
2377
        pop     ebx
2378
 
3647 hidnplayr 2379
        pusha
2380
        mov     ecx, socket_mutex
2381
        call    mutex_unlock
2382
        popa
2383
 
3545 hidnplayr 2384
        ret
2385
 
2386
 
2387
 
2388
 
2389
;-----------------------------------------------------------------
2390
;
2391
; SOCKET_is_connecting
2392
;
2393
;  IN:  eax = socket ptr
2394
;  OUT: /
2395
;
2396
;-----------------------------------------------------------------
2397
 
2398
align 4
2399
SOCKET_is_connecting:
2400
 
3556 hidnplayr 2401
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2402
 
2403
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2404
        or      [eax + SOCKET.options], SS_ISCONNECTING
2405
 
2406
        jmp     SOCKET_notify
2407
 
2408
 
2409
 
2410
;-----------------------------------------------------------------
2411
;
2412
; SOCKET_is_connected
2413
;
2414
;  IN:  eax = socket ptr
2415
;  OUT: /
2416
;
2417
;-----------------------------------------------------------------
2418
 
2419
align 4
2420
SOCKET_is_connected:
2421
 
3556 hidnplayr 2422
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2423
 
3674 hidnplayr 2424
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2425
        or      [eax + SOCKET.state], SS_ISCONNECTED
3545 hidnplayr 2426
 
2427
        jmp     SOCKET_notify
2428
 
2429
 
2430
 
2431
 
2432
;-----------------------------------------------------------------
2433
;
2434
; SOCKET_is_disconnecting
2435
;
2436
;  IN:  eax = socket ptr
2437
;  OUT: /
2438
;
2439
;-----------------------------------------------------------------
2440
 
2441
align 4
2442
SOCKET_is_disconnecting:
2443
 
3556 hidnplayr 2444
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2445
 
3674 hidnplayr 2446
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2447
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2448
 
2449
        jmp     SOCKET_notify
2450
 
2451
 
2452
 
2453
;-----------------------------------------------------------------
2454
;
2455
; SOCKET_is_disconnected
2456
;
2457
;  IN:  eax = socket ptr
2458
;  OUT: /
2459
;
2460
;-----------------------------------------------------------------
2461
 
2462
align 4
2463
SOCKET_is_disconnected:
2464
 
3556 hidnplayr 2465
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2466
 
3674 hidnplayr 2467
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2468
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2469
 
2470
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2471
        je      .tcp
2472
 
2473
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
2474
        je      .udp
2475
 
2476
        jmp     SOCKET_notify
2477
 
2478
  .tcp:
2479
  .udp:
2480
        mov     [eax + UDP_SOCKET.LocalPort], 0         ; UDP and TCP structs store localport at the same offset
2481
        mov     [eax + UDP_SOCKET.RemotePort], 0
2482
 
2483
        jmp     SOCKET_notify
2484
 
2485
 
2486
;-----------------------------------------------------------------
2487
;
2488
; SOCKET_cant_recv_more
2489
;
2490
;  IN:  eax = socket ptr
2491
;  OUT: /
2492
;
2493
;-----------------------------------------------------------------
2494
 
2495
align 4
2496
SOCKET_cant_recv_more:
2497
 
3556 hidnplayr 2498
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2499
 
3674 hidnplayr 2500
        or      [eax + SOCKET.state], SS_CANTRCVMORE
3545 hidnplayr 2501
 
3565 hidnplayr 2502
        call    SOCKET_notify
2503
 
3545 hidnplayr 2504
        ret
2505
 
2506
 
2507
 
2508
;-----------------------------------------------------------------
2509
;
2510
; SOCKET_cant_send_more
2511
;
2512
;  IN:  eax = socket ptr
2513
;  OUT: /
2514
;
2515
;-----------------------------------------------------------------
2516
 
2517
align 4
2518
SOCKET_cant_send_more:
2519
 
3556 hidnplayr 2520
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2521
 
3674 hidnplayr 2522
        or      [eax + SOCKET.state], SS_CANTSENDMORE
3658 hidnplayr 2523
        mov     [eax + SOCKET.snd_proc], .notconn
3545 hidnplayr 2524
 
3565 hidnplayr 2525
        call    SOCKET_notify
2526
 
3658 hidnplayr 2527
        ret
2528
 
2529
  .notconn:
3673 hidnplayr 2530
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2531
        mov     dword[esp+32], -1
3545 hidnplayr 2532
        ret