Subversion Repositories Kolibri OS

Rev

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

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