Subversion Repositories Kolibri OS

Rev

Rev 3737 | Rev 3861 | 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
611
        jz      .loop
3545 hidnplayr 612
 
3674 hidnplayr 613
        mov     dword[esp+20], EWOULDBLOCK
3704 hidnplayr 614
        mov     dword[esp+32], -1
3674 hidnplayr 615
        ret
616
 
617
  .loop:
618
        cmp     [eax + TCP_SOCKET.t_state], TCPS_CLOSED
619
        je      .fail
3698 hidnplayr 620
        cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
621
        je      .established
622
        ja      .fail
3674 hidnplayr 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
 
3698 hidnplayr 633
  .established:
3658 hidnplayr 634
        mov     dword[esp+32], 0
3545 hidnplayr 635
        ret
636
 
3674 hidnplayr 637
 
3545 hidnplayr 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
 
3658 hidnplayr 655
        mov     dword[esp+32], 0
3545 hidnplayr 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
 
3556 hidnplayr 671
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3545 hidnplayr 672
 
673
        call    SOCKET_num_to_ptr
3658 hidnplayr 674
        jz      .invalid
3545 hidnplayr 675
 
676
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 677
        jne     .notsupp
3545 hidnplayr 678
 
679
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 680
        jne     .invalid
3545 hidnplayr 681
 
682
        cmp     [eax + TCP_SOCKET.LocalPort], 0
3658 hidnplayr 683
        je      .already
3545 hidnplayr 684
 
685
        cmp     [eax + IP_SOCKET.LocalIP], 0
686
        jne     @f
3601 hidnplayr 687
        push    [IP_LIST + 4]           ;;; fixme!!!!
3545 hidnplayr 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
 
3658 hidnplayr 705
        mov     dword[esp+32], 0
706
        ret
3545 hidnplayr 707
 
3658 hidnplayr 708
  .notsupp:
3673 hidnplayr 709
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 710
        mov     dword[esp+32], -1
3545 hidnplayr 711
        ret
712
 
3658 hidnplayr 713
  .invalid:
3673 hidnplayr 714
        mov     dword[esp+20], EINVAL
3658 hidnplayr 715
        mov     dword[esp+32], -1
716
        ret
3545 hidnplayr 717
 
3658 hidnplayr 718
  .already:
3673 hidnplayr 719
        mov     dword[esp+20], EALREADY
3658 hidnplayr 720
        mov     dword[esp+32], -1
721
        ret
722
 
723
 
3545 hidnplayr 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
 
3556 hidnplayr 737
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 738
 
739
        call    SOCKET_num_to_ptr
3658 hidnplayr 740
        jz      .invalid
3545 hidnplayr 741
 
742
        test    [eax + SOCKET.options], SO_ACCEPTCON
3658 hidnplayr 743
        jz      .invalid
3545 hidnplayr 744
 
745
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 746
        jne     .notsupp
3545 hidnplayr 747
 
748
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 749
        jne     .invalid
3545 hidnplayr 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
 
3817 hidnplayr 762
; Convert it to a socket number
763
        call    SOCKET_ptr_to_num
764
        jz      .invalid        ; FIXME ?
765
 
3545 hidnplayr 766
; and return it to caller
767
        mov     [esp+32], eax
768
        ret
769
 
770
  .block:
771
        test    [eax + SOCKET.options], SO_NONBLOCK
3658 hidnplayr 772
        jnz     .wouldblock
3545 hidnplayr 773
 
774
        call    SOCKET_block
775
        jmp     .loop
776
 
3658 hidnplayr 777
  .wouldblock:
3673 hidnplayr 778
        mov     dword[esp+20], EWOULDBLOCK
3658 hidnplayr 779
        mov     dword[esp+32], -1
780
        ret
781
 
782
  .invalid:
3673 hidnplayr 783
        mov     dword[esp+20], EINVAL
3658 hidnplayr 784
        mov     dword[esp+32], -1
785
        ret
786
 
787
  .notsupp:
3673 hidnplayr 788
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 789
        mov     dword[esp+32], -1
790
        ret
791
 
3545 hidnplayr 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
 
3556 hidnplayr 803
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3545 hidnplayr 804
 
805
        call    SOCKET_num_to_ptr
3658 hidnplayr 806
        jz      .invalid
3545 hidnplayr 807
 
3658 hidnplayr 808
        mov     dword[esp+32], 0                                ; The socket exists, so we will succeed in closing it.
3545 hidnplayr 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?
813
        jz      @f
814
        call    SOCKET_notify.unblock                           ; Unblock it.
815
  @@:
816
 
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??
3646 hidnplayr 833
        call    SOCKET_free
3545 hidnplayr 834
 
835
        ret
836
 
837
 
3658 hidnplayr 838
  .invalid:
3673 hidnplayr 839
        mov     dword[esp+20], EINVAL
3658 hidnplayr 840
        mov     dword[esp+32], -1
841
        ret
842
 
843
 
3545 hidnplayr 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
 
3556 hidnplayr 858
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 859
 
860
        call    SOCKET_num_to_ptr
3658 hidnplayr 861
        jz      .invalid
3545 hidnplayr 862
 
3704 hidnplayr 863
  .loop:
864
        push    edi
3565 hidnplayr 865
        call    [eax + SOCKET.rcv_proc]
3704 hidnplayr 866
        pop     edi
3545 hidnplayr 867
 
3704 hidnplayr 868
        cmp     ebx, EWOULDBLOCK
869
        jne     .return
870
 
871
        test    edi, MSG_DONTWAIT
872
        jnz     .return_err
873
 
3737 hidnplayr 874
        test    [eax + SOCKET.state], SS_CANTRCVMORE
875
        jnz     .return_err
876
 
3704 hidnplayr 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:
3673 hidnplayr 890
        mov     [esp+20], ebx
3565 hidnplayr 891
        mov     [esp+32], eax
892
        ret
3545 hidnplayr 893
 
3565 hidnplayr 894
 
3658 hidnplayr 895
 
3704 hidnplayr 896
 
897
 
3545 hidnplayr 898
align 4
899
SOCKET_receive_dgram:
3704 hidnplayr 900
 
3556 hidnplayr 901
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 902
 
3704 hidnplayr 903
        mov     ebx, esi                                        ; bufferlength
3545 hidnplayr 904
 
3704 hidnplayr 905
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
3545 hidnplayr 906
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 907
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 908
 
3704 hidnplayr 909
        cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
3545 hidnplayr 910
        ja      .too_small
911
 
3565 hidnplayr 912
        push    ecx
3545 hidnplayr 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]
3556 hidnplayr 915
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 916
 
3704 hidnplayr 917
; copy the data from kernel buffer to application buffer
918
        mov     edi, edx                                        ; bufferaddr
3545 hidnplayr 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
3711 clevermous 929
        rep movsd
3545 hidnplayr 930
  .nd:
931
 
3704 hidnplayr 932
        call    kernel_free                                     ; free kernel buffer
933
        pop     eax                                             ; return number of bytes copied to application
934
        xor     ebx, ebx
3545 hidnplayr 935
        ret
936
 
937
  .too_small:
3565 hidnplayr 938
        mov     eax, -1
3704 hidnplayr 939
        push    EMSGSIZE
940
        pop     ebx
3565 hidnplayr 941
        ret
3545 hidnplayr 942
 
3658 hidnplayr 943
  .wouldblock:
3704 hidnplayr 944
        push    EWOULDBLOCK
945
        pop     ebx
3658 hidnplayr 946
        ret
3545 hidnplayr 947
 
3658 hidnplayr 948
 
3704 hidnplayr 949
 
3545 hidnplayr 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
958
        mov     ebx, [TASK_BASE]
959
        mov     ebx, [ebx + TASKDATA.pid]
960
        mov     [eax + SOCKET.PID], ebx
3704 hidnplayr 961
        mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
3545 hidnplayr 962
      @@:
963
 
964
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
965
 
3704 hidnplayr 966
; ... continue to SOCKET_receive_stream
967
 
3545 hidnplayr 968
align 4
969
SOCKET_receive_stream:
970
 
3556 hidnplayr 971
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 972
 
3704 hidnplayr 973
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
974
        je      .wouldblock
975
 
976
        test    edi, MSG_PEEK
977
        jnz     .peek
978
 
3545 hidnplayr 979
        mov     ecx, esi
980
        mov     edi, edx
981
        xor     edx, edx
982
 
983
        add     eax, STREAM_SOCKET.rcv
3704 hidnplayr 984
        call    SOCKET_ring_read                                ; copy data from kernel buffer to application buffer
985
        call    SOCKET_ring_free                                ; free read memory
3545 hidnplayr 986
 
3704 hidnplayr 987
        mov     eax, ecx                                        ; return number of bytes copied
988
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
3545 hidnplayr 989
        ret
990
 
3704 hidnplayr 991
  .wouldblock:
992
        push    EWOULDBLOCK
993
        pop     ebx
994
        ret
995
 
3545 hidnplayr 996
  .peek:
3565 hidnplayr 997
        mov     eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3704 hidnplayr 998
        xor     ebx, ebx
3545 hidnplayr 999
        ret
1000
 
1001
 
1002
;-----------------------------------------------------------------
1003
;
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:
1016
 
3556 hidnplayr 1017
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 1018
 
1019
        call    SOCKET_num_to_ptr
3658 hidnplayr 1020
        jz      .invalid
3545 hidnplayr 1021
 
1022
        mov     ecx, esi
1023
        mov     esi, edx
1024
 
1025
        jmp     [eax + SOCKET.snd_proc]
1026
 
3658 hidnplayr 1027
  .invalid:
3673 hidnplayr 1028
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1029
        mov     dword[esp+32], -1
1030
        ret
3545 hidnplayr 1031
 
3658 hidnplayr 1032
 
3545 hidnplayr 1033
align 4
1034
SOCKET_send_udp:
1035
 
3556 hidnplayr 1036
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 1037
 
1038
        mov     [esp+32], ecx
1039
        call    UDP_output
1040
        cmp     eax, -1
3658 hidnplayr 1041
        je      .error
3545 hidnplayr 1042
        ret
1043
 
3658 hidnplayr 1044
  .error:
1045
        mov     dword[esp+32], -1
3673 hidnplayr 1046
        mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
3658 hidnplayr 1047
        ret
3545 hidnplayr 1048
 
3658 hidnplayr 1049
 
3545 hidnplayr 1050
align 4
1051
SOCKET_send_tcp:
1052
 
3556 hidnplayr 1053
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 1054
 
1055
        push    eax
1056
        add     eax, STREAM_SOCKET.snd
1057
        call    SOCKET_ring_write
1058
        pop     eax
1059
 
1060
        mov     [esp+32], ecx
3658 hidnplayr 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]
3673 hidnplayr 1066
        mov     [esp+20], eax
3545 hidnplayr 1067
        ret
1068
 
1069
 
1070
align 4
1071
SOCKET_send_ip:
1072
 
3556 hidnplayr 1073
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 1074
 
1075
        mov     [esp+32], ecx
3658 hidnplayr 1076
        call    IPv4_output_raw         ; FIXME: IPv4_output_raw should return error codes!
3545 hidnplayr 1077
        cmp     eax, -1
3658 hidnplayr 1078
        je      .error
3545 hidnplayr 1079
        ret
1080
 
3658 hidnplayr 1081
  .error:
1082
        mov     dword[esp+32], -1
3673 hidnplayr 1083
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1084
        ret
3545 hidnplayr 1085
 
3658 hidnplayr 1086
 
3545 hidnplayr 1087
align 4
1088
SOCKET_send_icmp:
1089
 
3556 hidnplayr 1090
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 1091
 
1092
        mov     [esp+32], ecx
3658 hidnplayr 1093
        call    ICMP_output_raw         ; FIXME: errorcodes
3545 hidnplayr 1094
        cmp     eax, -1
3658 hidnplayr 1095
        je      .error
3545 hidnplayr 1096
        ret
1097
 
3658 hidnplayr 1098
  .error:
1099
        mov     dword[esp+32], -1
3673 hidnplayr 1100
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1101
        ret
3545 hidnplayr 1102
 
3658 hidnplayr 1103
 
3545 hidnplayr 1104
align 4
1105
SOCKET_send_pppoe:
1106
 
3556 hidnplayr 1107
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3545 hidnplayr 1108
 
1109
        mov     [esp+32], ecx
1110
        mov     ebx, [eax + SOCKET.device]
1111
 
3658 hidnplayr 1112
        call    PPPoE_discovery_output  ; FIXME: errorcodes
3545 hidnplayr 1113
        cmp     eax, -1
3658 hidnplayr 1114
        je      .error
3545 hidnplayr 1115
        ret
1116
 
3658 hidnplayr 1117
  .error:
1118
        mov     dword[esp+32], -1
3673 hidnplayr 1119
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1120
        ret
3545 hidnplayr 1121
 
1122
 
3658 hidnplayr 1123
 
3545 hidnplayr 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
 
3556 hidnplayr 1142
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1143
 
1144
        ; get the other side's socket and check if it still exists
1145
        mov     eax, [eax + SOCKET.device]
1146
        call    SOCKET_check
3658 hidnplayr 1147
        jz      .invalid
3545 hidnplayr 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
 
3658 hidnplayr 1163
  .invalid:
1164
        mov     dword[esp+32], -1
3673 hidnplayr 1165
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1166
        ret
3545 hidnplayr 1167
 
3658 hidnplayr 1168
 
3545 hidnplayr 1169
;-----------------------------------------------------------------
1170
;
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:
1185
 
3556 hidnplayr 1186
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1187
 
1188
        call    SOCKET_num_to_ptr
3658 hidnplayr 1189
        jz      .invalid
3545 hidnplayr 1190
 
1191
        cmp     dword [edx], IP_PROTO_TCP
3658 hidnplayr 1192
        jne     .invalid
3545 hidnplayr 1193
        cmp     dword [edx+4], -2
1194
        je      @f
1195
        cmp     dword [edx+4], -3
3658 hidnplayr 1196
        jne     .invalid
3545 hidnplayr 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
1219
        ret
1220
 
3658 hidnplayr 1221
  .invalid:
1222
        mov     dword[esp+32], -1
3673 hidnplayr 1223
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1224
        ret
3545 hidnplayr 1225
 
1226
 
3658 hidnplayr 1227
 
3545 hidnplayr 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
 
3556 hidnplayr 1241
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1242
 
1243
        call    SOCKET_num_to_ptr
3658 hidnplayr 1244
        jz      .invalid
3545 hidnplayr 1245
 
1246
        cmp     dword [edx], SOL_SOCKET
3658 hidnplayr 1247
        jne     .invalid
3545 hidnplayr 1248
 
1249
        cmp     dword [edx+4], SO_BINDTODEVICE
1250
        je      .bind
1251
 
3658 hidnplayr 1252
  .invalid:
1253
        mov     dword[esp+32], -1
3673 hidnplayr 1254
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1255
        ret
3545 hidnplayr 1256
 
1257
  .bind:
3658 hidnplayr 1258
        cmp     dword[edx+8], 0
3545 hidnplayr 1259
        je      .unbind
1260
 
3658 hidnplayr 1261
        movzx   edx, byte[edx + 9]
3600 hidnplayr 1262
        cmp     edx, NET_DEVICES_MAX
3658 hidnplayr 1263
        ja      .invalid
3545 hidnplayr 1264
 
1265
        mov     edx, [NET_DRV_LIST + 4*edx]
1266
        test    edx, edx
3658 hidnplayr 1267
        jz      .already
3545 hidnplayr 1268
        mov     [eax + SOCKET.device], edx
1269
 
3556 hidnplayr 1270
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
3545 hidnplayr 1271
 
3658 hidnplayr 1272
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1273
        ret
1274
 
1275
  .unbind:
1276
        mov     [eax + SOCKET.device], 0
1277
 
3658 hidnplayr 1278
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1279
        ret
1280
 
3658 hidnplayr 1281
  .already:
3673 hidnplayr 1282
        mov     dword[esp+20], EALREADY
3658 hidnplayr 1283
        mov     dword[esp+32], -1
1284
        ret
3545 hidnplayr 1285
 
1286
 
3658 hidnplayr 1287
 
1288
 
3545 hidnplayr 1289
;-----------------------------------------------------------------
1290
;
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:
1302
 
3556 hidnplayr 1303
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1304
 
1305
        call    SOCKET_alloc
3658 hidnplayr 1306
        jz      .nomem1
3545 hidnplayr 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
3658 hidnplayr 1318
        jz      .nomem2
3673 hidnplayr 1319
        mov     [esp+20], edi   ; application's ebx
3545 hidnplayr 1320
 
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
 
1339
        ret
1340
 
3658 hidnplayr 1341
  .nomem2:
3545 hidnplayr 1342
        mov     eax, ebx
1343
        call    SOCKET_free
3658 hidnplayr 1344
  .nomem1:
1345
        mov     dword[esp+32], -1
1346
        mov     dword[esp+28], ENOMEM
1347
        ret
3545 hidnplayr 1348
 
1349
 
1350
 
1351
;-----------------------------------------------------------------
1352
;
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
 
3556 hidnplayr 1365
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1366
 
1367
        mov     edi, edx
1368
 
1369
        test    ecx, ecx
1370
        jz      .returnall
1371
 
1372
        call    SOCKET_num_to_ptr
3658 hidnplayr 1373
        jz      .invalid
3545 hidnplayr 1374
 
1375
        mov     esi, eax
1376
        mov     ecx, SOCKETBUFFSIZE/4
3711 clevermous 1377
        rep movsd
3545 hidnplayr 1378
 
3658 hidnplayr 1379
        mov     dword[esp+32], 0
3545 hidnplayr 1380
        ret
1381
 
1382
  .returnall:
1383
        mov     ebx, net_sockets
1384
  .next_socket:
1385
        mov     ebx, [ebx + SOCKET.NextPtr]
1386
        test    ebx, ebx
1387
        jz      .done
1388
        mov     eax, [ebx + SOCKET.Number]
1389
        stosd
1390
        jmp     .next_socket
1391
  .done:
1392
        xor     eax, eax
1393
        stosd
3658 hidnplayr 1394
        mov     dword[esp+32], eax
1395
        ret
3545 hidnplayr 1396
 
3658 hidnplayr 1397
  .invalid:
1398
        mov     dword[esp+32], -1
1399
        mov     dword[esp+28], EINVAL
3545 hidnplayr 1400
        ret
1401
 
1402
 
1403
;-----------------------------------------------------------------
1404
;
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:
1417
 
3556 hidnplayr 1418
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1419
 
1420
        push    ebx esi ecx
1421
 
1422
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1423
        je      .udp
1424
 
1425
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1426
        je      .tcp
1427
 
1428
        pop     ecx esi ebx
1429
        ret
1430
 
1431
  .udp:
1432
        mov     bx, [last_UDP_port]
1433
        call    .findit
1434
        mov     [last_UDP_port], bx
1435
 
1436
        pop     ecx esi ebx
1437
        ret
1438
 
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
;-----------------------------------------------------------------
1464
;
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:
1478
 
3556 hidnplayr 1479
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1480
 
3647 hidnplayr 1481
        pusha
1482
        mov     ecx, socket_mutex
1483
        call    mutex_lock
1484
        popa
1485
 
3545 hidnplayr 1486
        mov     ecx, [eax + SOCKET.Protocol]
1487
        mov     edx, [eax + IP_SOCKET.LocalIP]
1488
        mov     esi, net_sockets
1489
 
1490
  .next_socket:
1491
        mov     esi, [esi + SOCKET.NextPtr]
1492
        or      esi, esi
1493
        jz      .port_ok
1494
 
1495
        cmp     [esi + SOCKET.Protocol], ecx
1496
        jne     .next_socket
1497
 
1498
        cmp     [esi + IP_SOCKET.LocalIP], edx
1499
        jne     .next_socket
1500
 
1501
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1502
        jne     .next_socket
1503
 
3647 hidnplayr 1504
        pusha
1505
        mov     ecx, socket_mutex
1506
        call    mutex_unlock
1507
        popa
1508
 
3556 hidnplayr 1509
        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 1510
        ret
1511
 
1512
  .port_ok:
3647 hidnplayr 1513
        pusha
1514
        mov     ecx, socket_mutex
1515
        call    mutex_unlock
1516
        popa
1517
 
3556 hidnplayr 1518
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1519
        mov     [eax + UDP_SOCKET.LocalPort], bx
1520
        or      bx, bx                                  ; clear the zero-flag
1521
        ret
1522
 
1523
 
1524
 
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:
1544
 
3556 hidnplayr 1545
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1546
 
1547
        mov     [esp+4], ecx
1548
        push    esi
1549
        mov     esi, esp
1550
 
1551
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1552
 
3556 hidnplayr 1553
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1554
        add     esp, sizeof.socket_queue_entry
1555
 
1556
        pusha
1557
        lea     ecx, [eax + SOCKET.mutex]
1558
        call    mutex_unlock
1559
        popa
1560
 
1561
        jmp     SOCKET_notify
1562
 
1563
  .full:
3556 hidnplayr 1564
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1565
 
1566
        pusha
1567
        lea     ecx, [eax + SOCKET.mutex]
1568
        call    mutex_unlock
1569
        popa
1570
 
1571
        call    kernel_free
1572
        add     esp, 8
1573
 
1574
        ret
1575
 
1576
 
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
 
3556 hidnplayr 1591
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
3545 hidnplayr 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
 
1607
        ret
1608
 
1609
;-----------------------------------------------------------------
1610
;
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:
1624
 
3556 hidnplayr 1625
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1626
 
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
1632
 
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]
3556 hidnplayr 1641
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 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
3711 clevermous 1668
        rep movsd
3545 hidnplayr 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
 
1678
        ret
1679
 
1680
;-----------------------------------------------------------------
1681
;
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:
1698
 
3556 hidnplayr 1699
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1700
 
1701
        pusha
1702
        lea     ecx, [eax + RING_BUFFER.mutex]
1703
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1704
        popa
1705
 
1706
        mov     esi, [eax + RING_BUFFER.read_ptr]
1707
        add     esi, edx                                        ; esi = start_ptr + offset
1708
 
1709
        neg     edx
1710
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1711
        jle     .no_data_at_all
1712
 
1713
        pusha
1714
        lea     ecx, [eax + RING_BUFFER.mutex]
1715
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1716
        popa
1717
 
1718
        cmp     ecx, edx
1719
        ja      .less_data
1720
 
1721
  .copy:
3556 hidnplayr 1722
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 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
3711 clevermous 1734
        rep movsd
3545 hidnplayr 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
1743
        popa
1744
 
3556 hidnplayr 1745
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1746
        xor     ecx, ecx
1747
        ret
1748
 
1749
  .less_data:
1750
        mov     ecx, edx
1751
        jmp     .copy
1752
 
1753
 
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:
1768
 
3556 hidnplayr 1769
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 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..
3556 hidnplayr 1794
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1795
        add     [eax + RING_BUFFER.size], ecx
1796
 
1797
        push    eax
1798
        lea     ecx, [eax + RING_BUFFER.mutex]
1799
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1800
        pop     eax
1801
 
1802
        xor     ecx, ecx
1803
        ret
1804
 
1805
 
1806
;-----------------------------------------------------------------
1807
;
1808
; SOCKET_block
1809
;
1810
; Suspends the thread attached to a socket
1811
;
1812
;  IN:  eax = socket ptr
3674 hidnplayr 1813
;  OUT: eax = unchanged
3545 hidnplayr 1814
;
1815
;-----------------------------------------------------------------
1816
align 4
1817
SOCKET_block:
1818
 
3556 hidnplayr 1819
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1820
 
1821
        pushf
3674 hidnplayr 1822
        push    eax
3545 hidnplayr 1823
        cli
1824
 
1825
        ; Set the 'socket is blocked' flag
1826
        or      [eax + SOCKET.state], SS_BLOCKED
1827
 
1828
        ; Suspend the thread
1829
        push    edx
1830
        mov     edx, [TASK_BASE]
1831
        mov     [edx + TASKDATA.state], 1               ; Suspended
1832
 
1833
        ; Remember the thread ID so we can wake it up again
1834
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1835
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1836
        mov     [eax + SOCKET.TID], edx
1837
        pop     edx
1838
 
1839
        call    change_task
3674 hidnplayr 1840
        pop     eax
3545 hidnplayr 1841
        popf
1842
 
3556 hidnplayr 1843
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
3545 hidnplayr 1844
 
1845
        ret
1846
 
1847
 
1848
;-----------------------------------------------------------------
1849
;
1850
; SOCKET_notify
1851
;
1852
; notify's the owner of a socket that something happened
1853
;
1854
;  IN:  eax = socket ptr
3674 hidnplayr 1855
;  OUT: eax = unchanged
3545 hidnplayr 1856
;
1857
;-----------------------------------------------------------------
1858
align 4
1859
SOCKET_notify:
1860
 
3556 hidnplayr 1861
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1862
 
1863
        call    SOCKET_check
1864
        jz      .error
1865
 
1866
        test    [eax + SOCKET.state], SS_BLOCKED
1867
        jnz     .unblock
1868
 
3704 hidnplayr 1869
;        test    [eax + SOCKET.options], SO_NONBLOCK
1870
;        jz      .error
3545 hidnplayr 1871
 
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
 
3817 hidnplayr 1897
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", eax
3545 hidnplayr 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
1908
        jz      .error
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:
1921
 
1922
        ; Run the thread
1923
        mov     [esi + TASKDATA.state], 0       ; Running
3556 hidnplayr 1924
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
3545 hidnplayr 1925
 
1926
  .done:
1927
        pop     esi ecx eax
1928
 
1929
  .error:
1930
        ret
1931
 
1932
 
1933
;--------------------------------------------------------------------
1934
;
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
3556 hidnplayr 1953
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1954
        or      eax, eax
1955
        jz      .exit
1956
 
1957
; zero-initialize allocated memory
1958
        push    eax
1959
        mov     edi, eax
1960
        mov     ecx, SOCKETBUFFSIZE / 4
1961
        xor     eax, eax
3711 clevermous 1962
        rep stosd
3545 hidnplayr 1963
        pop     eax
1964
 
1965
; set send-and receive procedures to return -1
3658 hidnplayr 1966
        mov     [eax + SOCKET.snd_proc], .not_yet
1967
        mov     [eax + SOCKET.rcv_proc], .not_yet
3545 hidnplayr 1968
 
3647 hidnplayr 1969
        pusha
1970
        mov     ecx, socket_mutex
1971
        call    mutex_lock
1972
        popa
1973
 
3545 hidnplayr 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
3556 hidnplayr 1994
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 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
2004
        lea     ecx, [eax + SOCKET.mutex]
2005
        call    mutex_init
2006
        popa
2007
 
2008
; add socket to the list by re-arranging some pointers
2009
        mov     ebx, [net_sockets + SOCKET.NextPtr]
2010
 
2011
        mov     [eax + SOCKET.PrevPtr], net_sockets
2012
        mov     [eax + SOCKET.NextPtr], ebx
2013
 
2014
        test    ebx, ebx
2015
        jz      @f
2016
 
2017
        pusha
2018
        lea     ecx, [ebx + SOCKET.mutex]
2019
        call    mutex_lock
2020
        popa
2021
 
2022
        mov     [ebx + SOCKET.PrevPtr], eax
2023
 
2024
        pusha
2025
        lea     ecx, [ebx + SOCKET.mutex]
2026
        call    mutex_unlock
2027
        popa
2028
       @@:
2029
 
2030
        mov     [net_sockets + SOCKET.NextPtr], eax
2031
        or      eax, eax                ; used to clear zero flag
3647 hidnplayr 2032
 
2033
        pusha
2034
        mov     ecx, socket_mutex
2035
        call    mutex_unlock
2036
        popa
2037
 
3545 hidnplayr 2038
  .exit:
2039
        pop     ebx
2040
 
2041
        ret
2042
 
3658 hidnplayr 2043
  .not_yet:
3673 hidnplayr 2044
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2045
        mov     dword[esp+32], -1
2046
        ret
3545 hidnplayr 2047
 
3658 hidnplayr 2048
 
3545 hidnplayr 2049
;----------------------------------------------------
2050
;
2051
; SOCKET_free
2052
;
2053
; Free socket data memory and remove socket from the list
2054
;
2055
; IN:  eax = socket ptr
2056
; OUT: /
2057
;
2058
;----------------------------------------------------
2059
align 4
2060
SOCKET_free:
2061
 
3556 hidnplayr 2062
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 2063
 
3652 hidnplayr 2064
        pusha
2065
        mov     ecx, socket_mutex
2066
        call    mutex_lock
2067
        popa
2068
 
3545 hidnplayr 2069
        call    SOCKET_check
2070
        jz      .error
2071
 
2072
        push    ebx
2073
 
2074
        pusha
2075
        lea     ecx, [eax + SOCKET.mutex]
2076
        call    mutex_lock
2077
        popa
2078
 
2079
        cmp     [eax + SOCKET.Domain], AF_INET4
2080
        jnz     .no_tcp
2081
 
2082
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2083
        jnz     .no_tcp
2084
 
2085
        mov     ebx, eax
2086
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
2087
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
2088
        mov     eax, ebx
2089
  .no_tcp:
2090
 
3652 hidnplayr 2091
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 2092
        push    eax                             ; this will be passed to kernel_free
2093
        mov     ebx, [eax + SOCKET.NextPtr]
2094
        mov     eax, [eax + SOCKET.PrevPtr]
2095
 
3556 hidnplayr 2096
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 2097
 
2098
        test    eax, eax
2099
        jz      @f
2100
        mov     [eax + SOCKET.NextPtr], ebx
2101
       @@:
2102
 
2103
        test    ebx, ebx
2104
        jz      @f
2105
        mov     [ebx + SOCKET.PrevPtr], eax
2106
       @@:
2107
 
2108
        call    kernel_free
2109
        pop     ebx
2110
 
3652 hidnplayr 2111
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
2112
 
2113
  .error:
2114
 
3647 hidnplayr 2115
        pusha
2116
        mov     ecx, socket_mutex
2117
        call    mutex_unlock
2118
        popa
2119
 
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
 
3648 hidnplayr 2334
        pushf
2335
        cli     ; FIXME
2336
 
3556 hidnplayr 2337
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2338
 
3647 hidnplayr 2339
        pusha
2340
        mov     ecx, socket_mutex
2341
        call    mutex_lock
2342
        popa
2343
 
3545 hidnplayr 2344
        push    ebx
2345
        mov     ebx, net_sockets
2346
 
2347
  .next_socket:
2348
        mov     ebx, [ebx + SOCKET.NextPtr]
2349
  .next_socket_test:
2350
        test    ebx, ebx
2351
        jz      .done
2352
 
2353
        cmp     [ebx + SOCKET.PID], edx
2354
        jne     .next_socket
2355
 
3556 hidnplayr 2356
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2357
 
2358
        mov     [ebx + SOCKET.PID], 0
2359
        mov     eax, ebx
2360
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2361
 
3545 hidnplayr 2362
        pusha
3648 hidnplayr 2363
        mov     ecx, socket_mutex
2364
        call    mutex_unlock
2365
        popa
2366
 
2367
        pusha
3652 hidnplayr 2368
        cmp     [eax + SOCKET.Domain], AF_INET4
2369
        jne     .free
2370
 
2371
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2372
        jne     .free
2373
 
2374
        call    TCP_close
2375
        jmp     .closed
2376
 
2377
  .free:
2378
        call    SOCKET_free
2379
 
2380
  .closed:
3545 hidnplayr 2381
        popa
3648 hidnplayr 2382
 
2383
        pusha
2384
        mov     ecx, socket_mutex
2385
        call    mutex_lock
2386
        popa
2387
 
3545 hidnplayr 2388
        jmp     .next_socket_test
2389
 
2390
  .done:
2391
        pop     ebx
2392
 
3647 hidnplayr 2393
        pusha
2394
        mov     ecx, socket_mutex
2395
        call    mutex_unlock
2396
        popa
2397
 
3648 hidnplayr 2398
        popf
2399
 
3545 hidnplayr 2400
        ret
2401
 
2402
 
2403
 
2404
 
2405
;-----------------------------------------------------------------
2406
;
2407
; SOCKET_is_connecting
2408
;
2409
;  IN:  eax = socket ptr
2410
;  OUT: /
2411
;
2412
;-----------------------------------------------------------------
2413
 
2414
align 4
2415
SOCKET_is_connecting:
2416
 
3556 hidnplayr 2417
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2418
 
2419
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2420
        or      [eax + SOCKET.options], SS_ISCONNECTING
2421
 
2422
        jmp     SOCKET_notify
2423
 
2424
 
2425
 
2426
;-----------------------------------------------------------------
2427
;
2428
; SOCKET_is_connected
2429
;
2430
;  IN:  eax = socket ptr
2431
;  OUT: /
2432
;
2433
;-----------------------------------------------------------------
2434
 
2435
align 4
2436
SOCKET_is_connected:
2437
 
3556 hidnplayr 2438
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2439
 
3674 hidnplayr 2440
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2441
        or      [eax + SOCKET.state], SS_ISCONNECTED
3545 hidnplayr 2442
 
2443
        jmp     SOCKET_notify
2444
 
2445
 
2446
 
2447
 
2448
;-----------------------------------------------------------------
2449
;
2450
; SOCKET_is_disconnecting
2451
;
2452
;  IN:  eax = socket ptr
2453
;  OUT: /
2454
;
2455
;-----------------------------------------------------------------
2456
 
2457
align 4
2458
SOCKET_is_disconnecting:
2459
 
3556 hidnplayr 2460
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2461
 
3674 hidnplayr 2462
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2463
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2464
 
2465
        jmp     SOCKET_notify
2466
 
2467
 
2468
 
2469
;-----------------------------------------------------------------
2470
;
2471
; SOCKET_is_disconnected
2472
;
2473
;  IN:  eax = socket ptr
2474
;  OUT: /
2475
;
2476
;-----------------------------------------------------------------
2477
 
2478
align 4
2479
SOCKET_is_disconnected:
2480
 
3556 hidnplayr 2481
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2482
 
3674 hidnplayr 2483
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2484
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2485
 
2486
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2487
        je      .tcp
2488
 
2489
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
2490
        je      .udp
2491
 
2492
        jmp     SOCKET_notify
2493
 
2494
  .tcp:
2495
  .udp:
2496
        mov     [eax + UDP_SOCKET.LocalPort], 0         ; UDP and TCP structs store localport at the same offset
2497
        mov     [eax + UDP_SOCKET.RemotePort], 0
2498
 
2499
        jmp     SOCKET_notify
2500
 
2501
 
2502
;-----------------------------------------------------------------
2503
;
2504
; SOCKET_cant_recv_more
2505
;
2506
;  IN:  eax = socket ptr
2507
;  OUT: /
2508
;
2509
;-----------------------------------------------------------------
2510
 
2511
align 4
2512
SOCKET_cant_recv_more:
2513
 
3556 hidnplayr 2514
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2515
 
3674 hidnplayr 2516
        or      [eax + SOCKET.state], SS_CANTRCVMORE
3545 hidnplayr 2517
 
3565 hidnplayr 2518
        call    SOCKET_notify
2519
 
3545 hidnplayr 2520
        ret
2521
 
2522
 
2523
 
2524
;-----------------------------------------------------------------
2525
;
2526
; SOCKET_cant_send_more
2527
;
2528
;  IN:  eax = socket ptr
2529
;  OUT: /
2530
;
2531
;-----------------------------------------------------------------
2532
 
2533
align 4
2534
SOCKET_cant_send_more:
2535
 
3556 hidnplayr 2536
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2537
 
3674 hidnplayr 2538
        or      [eax + SOCKET.state], SS_CANTSENDMORE
3658 hidnplayr 2539
        mov     [eax + SOCKET.snd_proc], .notconn
3545 hidnplayr 2540
 
3565 hidnplayr 2541
        call    SOCKET_notify
2542
 
3658 hidnplayr 2543
        ret
2544
 
2545
  .notconn:
3673 hidnplayr 2546
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2547
        mov     dword[esp+32], -1
3545 hidnplayr 2548
        ret