Subversion Repositories Kolibri OS

Rev

Rev 3674 | Rev 3704 | 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
218
        rep     stosd
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
 
303
;        push    edx
304
;        and     edx, SO_NONBLOCK
3674 hidnplayr 305
        or      [eax + SOCKET.options], SO_NONBLOCK ;edx        ; HACK: make all sockets non-blocking untill API and applications are fixed
3545 hidnplayr 306
;        pop     edx
307
;        and     edx, not SO_NONBLOCK
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
614
        mov     dword[esp+32], 0                 ; Should be -1? or not?
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
 
3658 hidnplayr 757
; Convert it to a socket number
758
        call    SOCKET_ptr_to_num
759
        jz      .invalid        ; FIXME ?
760
 
3545 hidnplayr 761
; Change thread ID to that of the current thread
762
        mov     ebx, [TASK_BASE]
763
        mov     ebx, [ebx + TASKDATA.pid]
764
        mov     [eax + SOCKET.TID], ebx
765
 
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
 
3565 hidnplayr 863
        call    [eax + SOCKET.rcv_proc]
3545 hidnplayr 864
 
3673 hidnplayr 865
        mov     [esp+20], ebx
3565 hidnplayr 866
        mov     [esp+32], eax
867
        ret
3545 hidnplayr 868
 
3565 hidnplayr 869
 
3658 hidnplayr 870
  .invalid:
3673 hidnplayr 871
        mov     dword[esp+20], EINVAL
3658 hidnplayr 872
        mov     dword[esp+32], -1
873
        ret
874
 
3545 hidnplayr 875
align 4
876
SOCKET_receive_dgram:
3556 hidnplayr 877
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 878
 
879
        mov     ebx, esi
880
        mov     edi, edx                                        ; addr to buffer
881
 
882
  .loop:
883
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block      ; destroys esi and ecx
884
 
885
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 886
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 887
 
888
        cmp     ecx, ebx
889
        ja      .too_small
890
 
3565 hidnplayr 891
        push    ecx
3545 hidnplayr 892
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
893
        mov     esi, [esi + socket_queue_entry.data_ptr]
3556 hidnplayr 894
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 895
 
896
; copy the data
897
        shr     ecx, 1
898
        jnc     .nb
899
        movsb
900
  .nb:
901
        shr     ecx, 1
902
        jnc     .nw
903
        movsw
904
  .nw:
905
        test    ecx, ecx
906
        jz      .nd
907
        rep     movsd
908
  .nd:
909
 
910
        call    kernel_free                                     ; remove the packet
3565 hidnplayr 911
        pop     eax
3545 hidnplayr 912
        ret
913
 
914
  .too_small:
3565 hidnplayr 915
        mov     eax, -1
3658 hidnplayr 916
        mov     ebx, EMSGSIZE
3565 hidnplayr 917
        ret
3545 hidnplayr 918
 
919
  .block:
920
        test    [eax + SOCKET.options], SO_NONBLOCK
3658 hidnplayr 921
        jnz     .wouldblock
3545 hidnplayr 922
 
923
        call    SOCKET_block
924
        jmp     .loop
925
 
3658 hidnplayr 926
  .wouldblock:
927
        mov     eax, -1
928
        mov     ebx, EWOULDBLOCK
929
        ret
3545 hidnplayr 930
 
3658 hidnplayr 931
 
3545 hidnplayr 932
align 4
933
SOCKET_receive_local:
934
 
935
        ; does this socket have a PID yet?
936
        cmp     [eax + SOCKET.PID], 0
937
        jne     @f
938
 
939
        ; Change PID to that of current process
940
        mov     ebx, [TASK_BASE]
941
        mov     ebx, [ebx + TASKDATA.pid]
942
        mov     [eax + SOCKET.PID], ebx
943
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
944
      @@:
945
 
946
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
947
 
948
align 4
949
SOCKET_receive_stream:
950
 
3556 hidnplayr 951
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 952
 
953
        mov     ebx, edi
954
        mov     ecx, esi
955
        mov     edi, edx
956
        xor     edx, edx
957
 
958
        test    ebx, MSG_DONTWAIT
959
        jnz     .dontwait
960
  .loop:
961
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
962
        je      .block
963
  .dontwait:
964
        test    ebx, MSG_PEEK
965
        jnz     .peek
966
 
967
        add     eax, STREAM_SOCKET.rcv
968
        call    SOCKET_ring_read
969
        call    SOCKET_ring_free
970
 
3565 hidnplayr 971
        mov     eax, ecx                ; return number of bytes copied
3545 hidnplayr 972
        ret
973
 
974
  .peek:
3565 hidnplayr 975
        mov     eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3545 hidnplayr 976
        ret
977
 
978
  .block:
979
        test    [eax + SOCKET.options], SO_NONBLOCK
3658 hidnplayr 980
        jnz     .wouldblock
3545 hidnplayr 981
 
982
        call    SOCKET_block
983
        jmp     .loop
984
 
985
  .return0:
3565 hidnplayr 986
        test    [eax + SOCKET.options], SS_CANTRCVMORE
987
        jz      .ok
988
 
989
        xor     eax, eax
990
        dec     eax
3545 hidnplayr 991
        ret
992
 
3565 hidnplayr 993
  .ok:
994
        xor     eax, eax
995
        ret
3545 hidnplayr 996
 
3658 hidnplayr 997
  .wouldblock:
998
        mov     eax, -1
999
        mov     ebx, EWOULDBLOCK
1000
        ret
3565 hidnplayr 1001
 
3658 hidnplayr 1002
 
1003
 
3545 hidnplayr 1004
;-----------------------------------------------------------------
1005
;
1006
; SOCKET_send
1007
;
1008
;
1009
;  IN:  socket number in ecx
1010
;       pointer to data in edx
1011
;       datalength in esi
1012
;       flags in edi
1013
;  OUT: -1 on error
1014
;
1015
;-----------------------------------------------------------------
1016
align 4
1017
SOCKET_send:
1018
 
3556 hidnplayr 1019
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 1020
 
1021
        call    SOCKET_num_to_ptr
3658 hidnplayr 1022
        jz      .invalid
3545 hidnplayr 1023
 
1024
        mov     ecx, esi
1025
        mov     esi, edx
1026
 
1027
        jmp     [eax + SOCKET.snd_proc]
1028
 
3658 hidnplayr 1029
  .invalid:
3673 hidnplayr 1030
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1031
        mov     dword[esp+32], -1
1032
        ret
3545 hidnplayr 1033
 
3658 hidnplayr 1034
 
3545 hidnplayr 1035
align 4
1036
SOCKET_send_udp:
1037
 
3556 hidnplayr 1038
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 1039
 
1040
        mov     [esp+32], ecx
1041
        call    UDP_output
1042
        cmp     eax, -1
3658 hidnplayr 1043
        je      .error
3545 hidnplayr 1044
        ret
1045
 
3658 hidnplayr 1046
  .error:
1047
        mov     dword[esp+32], -1
3673 hidnplayr 1048
        mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
3658 hidnplayr 1049
        ret
3545 hidnplayr 1050
 
3658 hidnplayr 1051
 
3545 hidnplayr 1052
align 4
1053
SOCKET_send_tcp:
1054
 
3556 hidnplayr 1055
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 1056
 
1057
        push    eax
1058
        add     eax, STREAM_SOCKET.snd
1059
        call    SOCKET_ring_write
1060
        pop     eax
1061
 
1062
        mov     [esp+32], ecx
3658 hidnplayr 1063
        mov     [eax + SOCKET.errorcode], 0
1064
        push    eax
1065
        call    TCP_output              ; FIXME: this doesnt look pretty, does it?
1066
        pop     eax
1067
        mov     eax, [eax + SOCKET.errorcode]
3673 hidnplayr 1068
        mov     [esp+20], eax
3545 hidnplayr 1069
        ret
1070
 
1071
 
1072
align 4
1073
SOCKET_send_ip:
1074
 
3556 hidnplayr 1075
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 1076
 
1077
        mov     [esp+32], ecx
3658 hidnplayr 1078
        call    IPv4_output_raw         ; FIXME: IPv4_output_raw should return error codes!
3545 hidnplayr 1079
        cmp     eax, -1
3658 hidnplayr 1080
        je      .error
3545 hidnplayr 1081
        ret
1082
 
3658 hidnplayr 1083
  .error:
1084
        mov     dword[esp+32], -1
3673 hidnplayr 1085
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1086
        ret
3545 hidnplayr 1087
 
3658 hidnplayr 1088
 
3545 hidnplayr 1089
align 4
1090
SOCKET_send_icmp:
1091
 
3556 hidnplayr 1092
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 1093
 
1094
        mov     [esp+32], ecx
3658 hidnplayr 1095
        call    ICMP_output_raw         ; FIXME: errorcodes
3545 hidnplayr 1096
        cmp     eax, -1
3658 hidnplayr 1097
        je      .error
3545 hidnplayr 1098
        ret
1099
 
3658 hidnplayr 1100
  .error:
1101
        mov     dword[esp+32], -1
3673 hidnplayr 1102
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1103
        ret
3545 hidnplayr 1104
 
3658 hidnplayr 1105
 
3545 hidnplayr 1106
align 4
1107
SOCKET_send_pppoe:
1108
 
3556 hidnplayr 1109
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3545 hidnplayr 1110
 
1111
        mov     [esp+32], ecx
1112
        mov     ebx, [eax + SOCKET.device]
1113
 
3658 hidnplayr 1114
        call    PPPoE_discovery_output  ; FIXME: errorcodes
3545 hidnplayr 1115
        cmp     eax, -1
3658 hidnplayr 1116
        je      .error
3545 hidnplayr 1117
        ret
1118
 
3658 hidnplayr 1119
  .error:
1120
        mov     dword[esp+32], -1
3673 hidnplayr 1121
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1122
        ret
3545 hidnplayr 1123
 
1124
 
3658 hidnplayr 1125
 
3545 hidnplayr 1126
align 4
1127
SOCKET_send_local:
1128
 
1129
        ; does this socket have a PID yet?
1130
        cmp     [eax + SOCKET.PID], 0
1131
        jne     @f
1132
 
1133
        ; Change PID to that of current process
1134
        mov     ebx, [TASK_BASE]
1135
        mov     ebx, [ebx + TASKDATA.pid]
1136
        mov     [eax + SOCKET.PID], ebx
1137
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1138
      @@:
1139
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
1140
 
1141
align 4
1142
SOCKET_send_local_:
1143
 
3556 hidnplayr 1144
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1145
 
1146
        ; get the other side's socket and check if it still exists
1147
        mov     eax, [eax + SOCKET.device]
1148
        call    SOCKET_check
3658 hidnplayr 1149
        jz      .invalid
3545 hidnplayr 1150
 
1151
        ; allright, shove in the data!
1152
        push    eax
1153
        add     eax, STREAM_SOCKET.rcv
1154
        call    SOCKET_ring_write
1155
        pop     eax
1156
 
1157
        ; return the number of written bytes (or errorcode) to application
1158
        mov     [esp+32], ecx
1159
 
1160
        ; and notify the other end
1161
        call    SOCKET_notify
1162
 
1163
        ret
1164
 
3658 hidnplayr 1165
  .invalid:
1166
        mov     dword[esp+32], -1
3673 hidnplayr 1167
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1168
        ret
3545 hidnplayr 1169
 
3658 hidnplayr 1170
 
3545 hidnplayr 1171
;-----------------------------------------------------------------
1172
;
1173
; SOCKET_get_options
1174
;
1175
;  IN:  ecx = socket number
1176
;       edx = pointer to the options:
1177
;               dd      level, optname, optval, optlen
1178
;  OUT: -1 on error
1179
;
1180
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
1181
; TODO: find best way to notify that send()'ed data were acknowledged
1182
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1183
;
1184
;-----------------------------------------------------------------
1185
align 4
1186
SOCKET_get_opt:
1187
 
3556 hidnplayr 1188
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1189
 
1190
        call    SOCKET_num_to_ptr
3658 hidnplayr 1191
        jz      .invalid
3545 hidnplayr 1192
 
1193
        cmp     dword [edx], IP_PROTO_TCP
3658 hidnplayr 1194
        jne     .invalid
3545 hidnplayr 1195
        cmp     dword [edx+4], -2
1196
        je      @f
1197
        cmp     dword [edx+4], -3
3658 hidnplayr 1198
        jne     .invalid
3545 hidnplayr 1199
@@:
1200
;        mov     eax, [edx+12]
1201
;        test    eax, eax
1202
;        jz      .fail
1203
;        cmp     dword [eax], 4
1204
;        mov     dword [eax], 4
1205
;        jb      .fail
1206
;        stdcall net_socket_num_to_addr, ecx
1207
;        test    eax, eax
1208
;        jz      .fail
1209
;        ; todo: check that eax is really TCP socket
1210
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
1211
;        cmp     dword [edx+4], -2
1212
;        jz      @f
1213
;        mov     ecx, [eax + TCP_SOCKET.state]
1214
@@:
1215
        mov     eax, [edx+8]
1216
        test    eax, eax
1217
        jz      @f
1218
        mov     [eax], ecx
1219
@@:
1220
        mov     dword [esp+32], 0
1221
        ret
1222
 
3658 hidnplayr 1223
  .invalid:
1224
        mov     dword[esp+32], -1
3673 hidnplayr 1225
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1226
        ret
3545 hidnplayr 1227
 
1228
 
3658 hidnplayr 1229
 
3545 hidnplayr 1230
;-----------------------------------------------------------------
1231
;
1232
; SOCKET_set_options
1233
;
1234
;  IN:  ecx = socket number
1235
;       edx = pointer to the options:
1236
;               dd      level, optname, optlen, optval
1237
;  OUT: -1 on error
1238
;
1239
;-----------------------------------------------------------------
1240
align 4
1241
SOCKET_set_opt:
1242
 
3556 hidnplayr 1243
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1244
 
1245
        call    SOCKET_num_to_ptr
3658 hidnplayr 1246
        jz      .invalid
3545 hidnplayr 1247
 
1248
        cmp     dword [edx], SOL_SOCKET
3658 hidnplayr 1249
        jne     .invalid
3545 hidnplayr 1250
 
1251
        cmp     dword [edx+4], SO_BINDTODEVICE
1252
        je      .bind
1253
 
1254
        cmp     dword [edx+4], SO_BLOCK
1255
        je      .block
1256
 
3658 hidnplayr 1257
  .invalid:
1258
        mov     dword[esp+32], -1
3673 hidnplayr 1259
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1260
        ret
3545 hidnplayr 1261
 
1262
  .bind:
3658 hidnplayr 1263
        cmp     dword[edx+8], 0
3545 hidnplayr 1264
        je      .unbind
1265
 
3658 hidnplayr 1266
        movzx   edx, byte[edx + 9]
3600 hidnplayr 1267
        cmp     edx, NET_DEVICES_MAX
3658 hidnplayr 1268
        ja      .invalid
3545 hidnplayr 1269
 
1270
        mov     edx, [NET_DRV_LIST + 4*edx]
1271
        test    edx, edx
3658 hidnplayr 1272
        jz      .already
3545 hidnplayr 1273
        mov     [eax + SOCKET.device], edx
1274
 
3556 hidnplayr 1275
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
3545 hidnplayr 1276
 
3658 hidnplayr 1277
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1278
        ret
1279
 
1280
  .unbind:
1281
        mov     [eax + SOCKET.device], 0
1282
 
3658 hidnplayr 1283
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1284
        ret
1285
 
1286
  .block:
3658 hidnplayr 1287
        cmp     dword[edx+8], 0
3545 hidnplayr 1288
        je      .unblock
1289
 
1290
        and     [eax + SOCKET.options], not SO_NONBLOCK
1291
 
3658 hidnplayr 1292
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1293
        ret
1294
 
1295
  .unblock:
1296
        or      [eax + SOCKET.options], SO_NONBLOCK
1297
 
3658 hidnplayr 1298
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1299
        ret
1300
 
3658 hidnplayr 1301
  .already:
3673 hidnplayr 1302
        mov     dword[esp+20], EALREADY
3658 hidnplayr 1303
        mov     dword[esp+32], -1
1304
        ret
3545 hidnplayr 1305
 
1306
 
3658 hidnplayr 1307
 
1308
 
3545 hidnplayr 1309
;-----------------------------------------------------------------
1310
;
1311
; SOCKET_pair
1312
;
1313
; Allocates a pair of linked LOCAL domain sockets
1314
;
1315
; IN: /
1316
; OUT: eax is socket1 num, -1 on error
1317
;      ebx is socket2 num
1318
;
1319
;-----------------------------------------------------------------
1320
align 4
1321
SOCKET_pair:
1322
 
3556 hidnplayr 1323
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1324
 
1325
        call    SOCKET_alloc
3658 hidnplayr 1326
        jz      .nomem1
3545 hidnplayr 1327
        mov     [esp+32], edi   ; application's eax
1328
 
1329
        mov     [eax + SOCKET.Domain], AF_LOCAL
1330
        mov     [eax + SOCKET.Type], SOCK_STREAM
1331
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1332
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1333
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1334
        mov     [eax + SOCKET.PID], 0
1335
        mov     ebx, eax
1336
 
1337
        call    SOCKET_alloc
3658 hidnplayr 1338
        jz      .nomem2
3673 hidnplayr 1339
        mov     [esp+20], edi   ; application's ebx
3545 hidnplayr 1340
 
1341
        mov     [eax + SOCKET.Domain], AF_LOCAL
1342
        mov     [eax + SOCKET.Type], SOCK_STREAM
1343
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1344
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1345
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1346
        mov     [eax + SOCKET.PID], 0
1347
 
1348
        ; Link the two sockets to eachother
1349
        mov     [eax + SOCKET.device], ebx
1350
        mov     [ebx + SOCKET.device], eax
1351
 
1352
        lea     eax, [eax + STREAM_SOCKET.rcv]
1353
        call    SOCKET_ring_create
1354
 
1355
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1356
        call    SOCKET_ring_create
1357
        pop     eax
1358
 
1359
        ret
1360
 
3658 hidnplayr 1361
  .nomem2:
3545 hidnplayr 1362
        mov     eax, ebx
1363
        call    SOCKET_free
3658 hidnplayr 1364
  .nomem1:
1365
        mov     dword[esp+32], -1
1366
        mov     dword[esp+28], ENOMEM
1367
        ret
3545 hidnplayr 1368
 
1369
 
1370
 
1371
;-----------------------------------------------------------------
1372
;
1373
; SOCKET_debug
1374
;
1375
;  Copies socket variables to application buffer
1376
;
1377
;  IN:  ecx = socket number
1378
;       edx = pointer to buffer
1379
;
1380
;  OUT: -1 on error
1381
;-----------------------------------------------------------------
1382
align 4
1383
SOCKET_debug:
1384
 
3556 hidnplayr 1385
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1386
 
1387
        mov     edi, edx
1388
 
1389
        test    ecx, ecx
1390
        jz      .returnall
1391
 
1392
        call    SOCKET_num_to_ptr
3658 hidnplayr 1393
        jz      .invalid
3545 hidnplayr 1394
 
1395
        mov     esi, eax
1396
        mov     ecx, SOCKETBUFFSIZE/4
1397
        rep     movsd
1398
 
3658 hidnplayr 1399
        mov     dword[esp+32], 0
3545 hidnplayr 1400
        ret
1401
 
1402
  .returnall:
1403
        mov     ebx, net_sockets
1404
  .next_socket:
1405
        mov     ebx, [ebx + SOCKET.NextPtr]
1406
        test    ebx, ebx
1407
        jz      .done
1408
        mov     eax, [ebx + SOCKET.Number]
1409
        stosd
1410
        jmp     .next_socket
1411
  .done:
1412
        xor     eax, eax
1413
        stosd
3658 hidnplayr 1414
        mov     dword[esp+32], eax
1415
        ret
3545 hidnplayr 1416
 
3658 hidnplayr 1417
  .invalid:
1418
        mov     dword[esp+32], -1
1419
        mov     dword[esp+28], EINVAL
3545 hidnplayr 1420
        ret
1421
 
1422
 
1423
;-----------------------------------------------------------------
1424
;
1425
; SOCKET_find_port
1426
;
1427
; Fills in the local port number for TCP and UDP sockets
1428
; This procedure always works because the number of sockets is
1429
; limited to a smaller number then the number of possible ports
1430
;
1431
;  IN:  eax = socket pointer
1432
;  OUT: /
1433
;
1434
;-----------------------------------------------------------------
1435
align 4
1436
SOCKET_find_port:
1437
 
3556 hidnplayr 1438
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1439
 
1440
        push    ebx esi ecx
1441
 
1442
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1443
        je      .udp
1444
 
1445
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1446
        je      .tcp
1447
 
1448
        pop     ecx esi ebx
1449
        ret
1450
 
1451
  .udp:
1452
        mov     bx, [last_UDP_port]
1453
        call    .findit
1454
        mov     [last_UDP_port], bx
1455
 
1456
        pop     ecx esi ebx
1457
        ret
1458
 
1459
  .tcp:
1460
        mov     bx, [last_TCP_port]
1461
        call    .findit
1462
        mov     [last_TCP_port], bx
1463
 
1464
        pop     ecx esi ebx
1465
        ret
1466
 
1467
 
1468
  .restart:
1469
        mov     bx, MIN_EPHEMERAL_PORT_N
1470
  .findit:
1471
        cmp     bx, MAX_EPHEMERAL_PORT_N
1472
        je      .restart
1473
 
1474
        add     bh, 1
1475
        adc     bl, 0
1476
 
1477
        call    SOCKET_check_port
1478
        jz      .findit
1479
        ret
1480
 
1481
 
1482
 
1483
;-----------------------------------------------------------------
1484
;
1485
; SOCKET_check_port (to be used with AF_INET only!)
1486
;
1487
; Checks if a local port number is unused
1488
; If the proposed port number is unused, it is filled in in the socket structure
1489
;
1490
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
1491
;        bx = proposed socket number (network byte order)
1492
;
1493
;  OUT:  ZF = set on error
1494
;
1495
;-----------------------------------------------------------------
1496
align 4
1497
SOCKET_check_port:
1498
 
3556 hidnplayr 1499
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1500
 
3647 hidnplayr 1501
        pusha
1502
        mov     ecx, socket_mutex
1503
        call    mutex_lock
1504
        popa
1505
 
3545 hidnplayr 1506
        mov     ecx, [eax + SOCKET.Protocol]
1507
        mov     edx, [eax + IP_SOCKET.LocalIP]
1508
        mov     esi, net_sockets
1509
 
1510
  .next_socket:
1511
        mov     esi, [esi + SOCKET.NextPtr]
1512
        or      esi, esi
1513
        jz      .port_ok
1514
 
1515
        cmp     [esi + SOCKET.Protocol], ecx
1516
        jne     .next_socket
1517
 
1518
        cmp     [esi + IP_SOCKET.LocalIP], edx
1519
        jne     .next_socket
1520
 
1521
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1522
        jne     .next_socket
1523
 
3647 hidnplayr 1524
        pusha
1525
        mov     ecx, socket_mutex
1526
        call    mutex_unlock
1527
        popa
1528
 
3556 hidnplayr 1529
        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 1530
        ret
1531
 
1532
  .port_ok:
3647 hidnplayr 1533
        pusha
1534
        mov     ecx, socket_mutex
1535
        call    mutex_unlock
1536
        popa
1537
 
3556 hidnplayr 1538
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1539
        mov     [eax + UDP_SOCKET.LocalPort], bx
1540
        or      bx, bx                                  ; clear the zero-flag
1541
        ret
1542
 
1543
 
1544
 
1545
;-----------------------------------------------------------------
1546
;
1547
; SOCKET_input
1548
;
1549
; Updates a (stateless) socket with received data
1550
;
1551
; Note: the mutex should already be set !
1552
;
1553
;  IN:  eax = socket ptr
1554
;       ecx = data size
1555
;       esi = ptr to data
1556
;       [esp] = ptr to buf
1557
;       [esp + 4] = buf size
1558
;
1559
;  OUT: /
1560
;
1561
;-----------------------------------------------------------------
1562
align 4
1563
SOCKET_input:
1564
 
3556 hidnplayr 1565
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1566
 
1567
        mov     [esp+4], ecx
1568
        push    esi
1569
        mov     esi, esp
1570
 
1571
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1572
 
3556 hidnplayr 1573
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1574
        add     esp, sizeof.socket_queue_entry
1575
 
1576
        pusha
1577
        lea     ecx, [eax + SOCKET.mutex]
1578
        call    mutex_unlock
1579
        popa
1580
 
1581
        jmp     SOCKET_notify
1582
 
1583
  .full:
3556 hidnplayr 1584
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1585
 
1586
        pusha
1587
        lea     ecx, [eax + SOCKET.mutex]
1588
        call    mutex_unlock
1589
        popa
1590
 
1591
        call    kernel_free
1592
        add     esp, 8
1593
 
1594
        ret
1595
 
1596
 
1597
;--------------------------
1598
;
1599
; eax = ptr to ring struct (just a buffer of the right size)
1600
;
1601
align 4
1602
SOCKET_ring_create:
1603
 
1604
        push    esi
1605
        mov     esi, eax
1606
 
1607
        push    edx
1608
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1609
        pop     edx
1610
 
3556 hidnplayr 1611
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
3545 hidnplayr 1612
 
1613
        pusha
1614
        lea     ecx, [esi + RING_BUFFER.mutex]
1615
        call    mutex_init
1616
        popa
1617
 
1618
        mov     [esi + RING_BUFFER.start_ptr], eax
1619
        mov     [esi + RING_BUFFER.write_ptr], eax
1620
        mov     [esi + RING_BUFFER.read_ptr], eax
1621
        mov     [esi + RING_BUFFER.size], 0
1622
        add     eax, SOCKET_MAXDATA
1623
        mov     [esi + RING_BUFFER.end_ptr], eax
1624
        mov     eax, esi
1625
        pop     esi
1626
 
1627
        ret
1628
 
1629
;-----------------------------------------------------------------
1630
;
1631
; SOCKET_ring_write
1632
;
1633
; Adds data to a stream socket, and updates write pointer and size
1634
;
1635
;  IN:  eax = ptr to ring struct
1636
;       ecx = data size
1637
;       esi = ptr to data
1638
;
1639
;  OUT: ecx = number of bytes stored
1640
;
1641
;-----------------------------------------------------------------
1642
align 4
1643
SOCKET_ring_write:
1644
 
3556 hidnplayr 1645
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1646
 
1647
; lock mutex
1648
        pusha
1649
        lea     ecx, [eax + RING_BUFFER.mutex]
1650
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1651
        popa
1652
 
1653
; calculate available size
1654
        mov     edi, SOCKET_MAXDATA
1655
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
1656
        cmp     ecx, edi
1657
        jbe     .copy
1658
        mov     ecx, edi
1659
  .copy:
1660
        mov     edi, [eax + RING_BUFFER.write_ptr]
3556 hidnplayr 1661
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1662
 
1663
; update write ptr
1664
        push    edi
1665
        add     edi, ecx
1666
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1667
        jb      @f
1668
        sub     edi, SOCKET_MAXDATA                             ; WRAP
1669
  @@:
1670
        mov     [eax + RING_BUFFER.write_ptr], edi
1671
        pop     edi
1672
 
1673
; update size
1674
        add     [eax + RING_BUFFER.size], ecx
1675
 
1676
; copy the data
1677
        push    ecx
1678
        shr     ecx, 1
1679
        jnc     .nb
1680
        movsb
1681
  .nb:
1682
        shr     ecx, 1
1683
        jnc     .nw
1684
        movsw
1685
  .nw:
1686
        test    ecx, ecx
1687
        jz      .nd
1688
        rep     movsd
1689
  .nd:
1690
        pop     ecx
1691
 
1692
; unlock mutex
1693
        push    eax ecx
1694
        lea     ecx, [eax + RING_BUFFER.mutex]
1695
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1696
        pop     ecx eax
1697
 
1698
        ret
1699
 
1700
;-----------------------------------------------------------------
1701
;
1702
; SOCKET_ring_read
1703
;
1704
;  IN:  eax = ring struct ptr
1705
;       ecx = bytes to read
1706
;       edx = offset
1707
;       edi = ptr to buffer start
1708
;
1709
;  OUT: eax = unchanged
1710
;       ecx = number of bytes read (0 on error)
1711
;       edx = destroyed
1712
;       esi = destroyed
1713
;       edi = ptr to buffer end
1714
;
1715
;-----------------------------------------------------------------
1716
align 4
1717
SOCKET_ring_read:
1718
 
3556 hidnplayr 1719
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1720
 
1721
        pusha
1722
        lea     ecx, [eax + RING_BUFFER.mutex]
1723
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1724
        popa
1725
 
1726
        mov     esi, [eax + RING_BUFFER.read_ptr]
1727
        add     esi, edx                                        ; esi = start_ptr + offset
1728
 
1729
        neg     edx
1730
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1731
        jle     .no_data_at_all
1732
 
1733
        pusha
1734
        lea     ecx, [eax + RING_BUFFER.mutex]
1735
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1736
        popa
1737
 
1738
        cmp     ecx, edx
1739
        ja      .less_data
1740
 
1741
  .copy:
3556 hidnplayr 1742
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1743
        push    ecx
1744
        shr     ecx, 1
1745
        jnc     .nb
1746
        movsb
1747
  .nb:
1748
        shr     ecx, 1
1749
        jnc     .nw
1750
        movsw
1751
  .nw:
1752
        test    ecx, ecx
1753
        jz      .nd
1754
        rep     movsd
1755
  .nd:
1756
        pop     ecx
1757
        ret
1758
 
1759
  .no_data_at_all:
1760
        pusha
1761
        lea     ecx, [eax + RING_BUFFER.mutex]
1762
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1763
        popa
1764
 
3556 hidnplayr 1765
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1766
        xor     ecx, ecx
1767
        ret
1768
 
1769
  .less_data:
1770
        mov     ecx, edx
1771
        jmp     .copy
1772
 
1773
 
1774
;-----------------------------------------------------------------
1775
;
1776
; SOCKET_ring_free
1777
;
1778
; Free's some bytes from the ringbuffer
1779
;
1780
;  IN:  eax = ptr to ring struct
1781
;       ecx = data size
1782
;
1783
;  OUT: ecx = number of bytes free-ed
1784
;
1785
;-----------------------------------------------------------------
1786
align 4
1787
SOCKET_ring_free:
1788
 
3556 hidnplayr 1789
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 1790
 
1791
        push    eax ecx
1792
        lea     ecx, [eax + RING_BUFFER.mutex]
1793
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1794
        pop     ecx eax
1795
 
1796
        sub     [eax + RING_BUFFER.size], ecx
1797
        jb      .error
1798
        add     [eax + RING_BUFFER.read_ptr], ecx
1799
 
1800
        mov     edx, [eax + RING_BUFFER.end_ptr]
1801
        cmp     [eax + RING_BUFFER.read_ptr], edx
1802
        jb      @f
1803
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1804
       @@:
1805
 
1806
        push    eax ecx
1807
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1808
        call    mutex_unlock
1809
        pop     ecx eax
1810
 
1811
        ret
1812
 
1813
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
3556 hidnplayr 1814
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1815
        add     [eax + RING_BUFFER.size], ecx
1816
 
1817
        push    eax
1818
        lea     ecx, [eax + RING_BUFFER.mutex]
1819
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1820
        pop     eax
1821
 
1822
        xor     ecx, ecx
1823
        ret
1824
 
1825
 
1826
;-----------------------------------------------------------------
1827
;
1828
; SOCKET_block
1829
;
1830
; Suspends the thread attached to a socket
1831
;
1832
;  IN:  eax = socket ptr
3674 hidnplayr 1833
;  OUT: eax = unchanged
3545 hidnplayr 1834
;
1835
;-----------------------------------------------------------------
1836
align 4
1837
SOCKET_block:
1838
 
3556 hidnplayr 1839
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1840
 
1841
        pushf
3674 hidnplayr 1842
        push    eax
3545 hidnplayr 1843
        cli
1844
 
1845
        ; Set the 'socket is blocked' flag
1846
        or      [eax + SOCKET.state], SS_BLOCKED
1847
 
1848
        ; Suspend the thread
1849
        push    edx
1850
        mov     edx, [TASK_BASE]
1851
        mov     [edx + TASKDATA.state], 1               ; Suspended
1852
 
1853
        ; Remember the thread ID so we can wake it up again
1854
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1855
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1856
        mov     [eax + SOCKET.TID], edx
1857
        pop     edx
1858
 
1859
        call    change_task
3674 hidnplayr 1860
        pop     eax
3545 hidnplayr 1861
        popf
1862
 
3556 hidnplayr 1863
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
3545 hidnplayr 1864
 
1865
        ret
1866
 
1867
 
1868
;-----------------------------------------------------------------
1869
;
1870
; SOCKET_notify
1871
;
1872
; notify's the owner of a socket that something happened
1873
;
1874
;  IN:  eax = socket ptr
3674 hidnplayr 1875
;  OUT: eax = unchanged
3545 hidnplayr 1876
;
1877
;-----------------------------------------------------------------
1878
align 4
1879
SOCKET_notify:
1880
 
3556 hidnplayr 1881
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1882
 
1883
        call    SOCKET_check
1884
        jz      .error
1885
 
1886
        test    [eax + SOCKET.state], SS_BLOCKED
1887
        jnz     .unblock
1888
 
1889
        test    [eax + SOCKET.options], SO_NONBLOCK
1890
        jz      .error
1891
 
1892
        push    eax ecx esi
1893
 
1894
; socket exists and is of non blocking type.
1895
; We'll try to flag an event to the thread
1896
 
1897
        mov     eax, [eax + SOCKET.TID]
1898
        test    eax, eax
1899
        jz      .done
1900
        mov     ecx, 1
1901
        mov     esi, TASK_DATA + TASKDATA.pid
1902
 
1903
  .next_pid:
1904
        cmp     [esi], eax
1905
        je      .found_pid
1906
        inc     ecx
1907
        add     esi, 0x20
1908
        cmp     ecx, [TASK_COUNT]
1909
        jbe     .next_pid
1910
; PID not found, TODO: close socket!
1911
        jmp     .done
1912
 
1913
  .found_pid:
1914
        shl     ecx, 8
1915
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1916
 
3556 hidnplayr 1917
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n"
3545 hidnplayr 1918
 
1919
        jmp     .done
1920
 
1921
  .unblock:
1922
        push    eax ecx esi
1923
        ; Clear the 'socket is blocked' flag
1924
        and     [eax + SOCKET.state], not SS_BLOCKED
1925
 
1926
        ; Find the thread's TASK_DATA
1927
        mov     eax, [eax + SOCKET.TID]
1928
        test    eax, eax
1929
        jz      .error
1930
        xor     ecx, ecx
1931
        inc     ecx
1932
        mov     esi, TASK_DATA
1933
  .next:
1934
        cmp     [esi + TASKDATA.pid], eax
1935
        je      .found
1936
        inc     ecx
1937
        add     esi, 0x20
1938
        cmp     ecx, [TASK_COUNT]
1939
        jbe     .next
1940
        jmp     .error
1941
  .found:
1942
 
1943
        ; Run the thread
1944
        mov     [esi + TASKDATA.state], 0       ; Running
3556 hidnplayr 1945
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
3545 hidnplayr 1946
 
1947
  .done:
1948
        pop     esi ecx eax
1949
 
1950
  .error:
1951
        ret
1952
 
1953
 
1954
;--------------------------------------------------------------------
1955
;
1956
; SOCKET_alloc
1957
;
1958
; Allocate memory for socket data and put new socket into the list
1959
; Newly created socket is initialized with calling PID and number and
1960
; put into beginning of list (which is a fastest way).
1961
;
1962
; IN:  /
1963
; OUT: eax = 0 on error, socket ptr otherwise
1964
;      edi = socket number
1965
;       ZF = cleared on error
1966
;
1967
;--------------------------------------------------------------------
1968
align 4
1969
SOCKET_alloc:
1970
 
1971
        push    ebx
1972
 
1973
        stdcall kernel_alloc, SOCKETBUFFSIZE
3556 hidnplayr 1974
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1975
        or      eax, eax
1976
        jz      .exit
1977
 
1978
; zero-initialize allocated memory
1979
        push    eax
1980
        mov     edi, eax
1981
        mov     ecx, SOCKETBUFFSIZE / 4
1982
        xor     eax, eax
1983
        rep     stosd
1984
        pop     eax
1985
 
1986
; set send-and receive procedures to return -1
3658 hidnplayr 1987
        mov     [eax + SOCKET.snd_proc], .not_yet
1988
        mov     [eax + SOCKET.rcv_proc], .not_yet
3545 hidnplayr 1989
 
3647 hidnplayr 1990
        pusha
1991
        mov     ecx, socket_mutex
1992
        call    mutex_lock
1993
        popa
1994
 
3545 hidnplayr 1995
; find first free socket number and use it
1996
        mov     edi, [last_socket_num]
1997
  .next_socket_number:
1998
        inc     edi
1999
        jz      .next_socket_number     ; avoid socket nr 0
2000
        cmp     edi, -1
2001
        je      .next_socket_number     ; avoid socket nr -1
2002
        mov     ebx, net_sockets
2003
  .next_socket:
2004
        mov     ebx, [ebx + SOCKET.NextPtr]
2005
        test    ebx, ebx
2006
        jz      .last_socket
2007
 
2008
        cmp     [ebx + SOCKET.Number], edi
2009
        jne     .next_socket
2010
        jmp     .next_socket_number
2011
 
2012
  .last_socket:
2013
        mov     [last_socket_num], edi
2014
        mov     [eax + SOCKET.Number], edi
3556 hidnplayr 2015
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 2016
 
2017
; Fill in PID
2018
        mov     ebx, [TASK_BASE]
2019
        mov     ebx, [ebx + TASKDATA.pid]
2020
        mov     [eax + SOCKET.PID], ebx
2021
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
2022
 
2023
; init mutex
2024
        pusha
2025
        lea     ecx, [eax + SOCKET.mutex]
2026
        call    mutex_init
2027
        popa
2028
 
2029
; add socket to the list by re-arranging some pointers
2030
        mov     ebx, [net_sockets + SOCKET.NextPtr]
2031
 
2032
        mov     [eax + SOCKET.PrevPtr], net_sockets
2033
        mov     [eax + SOCKET.NextPtr], ebx
2034
 
2035
        test    ebx, ebx
2036
        jz      @f
2037
 
2038
        pusha
2039
        lea     ecx, [ebx + SOCKET.mutex]
2040
        call    mutex_lock
2041
        popa
2042
 
2043
        mov     [ebx + SOCKET.PrevPtr], eax
2044
 
2045
        pusha
2046
        lea     ecx, [ebx + SOCKET.mutex]
2047
        call    mutex_unlock
2048
        popa
2049
       @@:
2050
 
2051
        mov     [net_sockets + SOCKET.NextPtr], eax
2052
        or      eax, eax                ; used to clear zero flag
3647 hidnplayr 2053
 
2054
        pusha
2055
        mov     ecx, socket_mutex
2056
        call    mutex_unlock
2057
        popa
2058
 
3545 hidnplayr 2059
  .exit:
2060
        pop     ebx
2061
 
2062
        ret
2063
 
3658 hidnplayr 2064
  .not_yet:
3673 hidnplayr 2065
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2066
        mov     dword[esp+32], -1
2067
        ret
3545 hidnplayr 2068
 
3658 hidnplayr 2069
 
3545 hidnplayr 2070
;----------------------------------------------------
2071
;
2072
; SOCKET_free
2073
;
2074
; Free socket data memory and remove socket from the list
2075
;
2076
; IN:  eax = socket ptr
2077
; OUT: /
2078
;
2079
;----------------------------------------------------
2080
align 4
2081
SOCKET_free:
2082
 
3556 hidnplayr 2083
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 2084
 
3652 hidnplayr 2085
        pusha
2086
        mov     ecx, socket_mutex
2087
        call    mutex_lock
2088
        popa
2089
 
3545 hidnplayr 2090
        call    SOCKET_check
2091
        jz      .error
2092
 
2093
        push    ebx
2094
 
2095
        pusha
2096
        lea     ecx, [eax + SOCKET.mutex]
2097
        call    mutex_lock
2098
        popa
2099
 
2100
        cmp     [eax + SOCKET.Domain], AF_INET4
2101
        jnz     .no_tcp
2102
 
2103
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2104
        jnz     .no_tcp
2105
 
2106
        mov     ebx, eax
2107
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
2108
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
2109
        mov     eax, ebx
2110
  .no_tcp:
2111
 
3652 hidnplayr 2112
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 2113
        push    eax                             ; this will be passed to kernel_free
2114
        mov     ebx, [eax + SOCKET.NextPtr]
2115
        mov     eax, [eax + SOCKET.PrevPtr]
2116
 
3556 hidnplayr 2117
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 2118
 
2119
        test    eax, eax
2120
        jz      @f
2121
        mov     [eax + SOCKET.NextPtr], ebx
2122
       @@:
2123
 
2124
        test    ebx, ebx
2125
        jz      @f
2126
        mov     [ebx + SOCKET.PrevPtr], eax
2127
       @@:
2128
 
2129
        call    kernel_free
2130
        pop     ebx
2131
 
3652 hidnplayr 2132
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
2133
 
2134
  .error:
2135
 
3647 hidnplayr 2136
        pusha
2137
        mov     ecx, socket_mutex
2138
        call    mutex_unlock
2139
        popa
2140
 
3545 hidnplayr 2141
        ret
2142
 
2143
;------------------------------------
2144
;
2145
; SOCKET_fork
2146
;
2147
; Create a child socket
2148
;
2149
; IN:  socket nr in ebx
2150
; OUT: child socket nr in eax
2151
;
2152
;-----------------------------------
2153
align 4
2154
SOCKET_fork:
2155
 
3556 hidnplayr 2156
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 2157
 
2158
; Exit if backlog queue is full
2159
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
2160
        cmp     ax, [ebx + SOCKET.backlog]
2161
        jae     .fail
2162
 
2163
; Allocate new socket
2164
        push    ebx
2165
        call    SOCKET_alloc
2166
        pop     ebx
2167
        jz      .fail
2168
 
2169
        push    eax
2170
        mov     esi, esp
2171
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
2172
        pop     eax
2173
 
2174
; Copy structure from current socket to new
2175
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
2176
        lea     esi, [ebx + SOCKET.PID]
2177
        lea     edi, [eax + SOCKET.PID]
2178
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
2179
        rep     movsd
2180
 
2181
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2182
 
2183
        ret
2184
 
2185
  .fail2:
2186
        add     esp, 4+4+4
2187
  .fail:
3556 hidnplayr 2188
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 2189
        xor     eax, eax
2190
        ret
2191
 
2192
 
2193
;---------------------------------------------------
2194
;
2195
; SOCKET_num_to_ptr
2196
;
2197
; Get socket structure address by its number
2198
;
2199
; IN:  ecx = socket number
2200
; OUT: eax = 0 on error, socket ptr otherwise
2201
;       ZF = set on error
2202
;
2203
;---------------------------------------------------
2204
align 4
2205
SOCKET_num_to_ptr:
2206
 
3556 hidnplayr 2207
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2208
 
3647 hidnplayr 2209
        pusha
2210
        mov     ecx, socket_mutex
2211
        call    mutex_lock
2212
        popa
2213
 
3545 hidnplayr 2214
        mov     eax, net_sockets
2215
 
2216
  .next_socket:
2217
        mov     eax, [eax + SOCKET.NextPtr]
2218
        or      eax, eax
2219
        jz      .error
2220
        cmp     [eax + SOCKET.Number], ecx
2221
        jne     .next_socket
2222
 
2223
        test    eax, eax
2224
 
3647 hidnplayr 2225
        pusha
2226
        mov     ecx, socket_mutex
2227
        call    mutex_unlock
2228
        popa
2229
 
3556 hidnplayr 2230
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2231
        ret
2232
 
2233
  .error:
3647 hidnplayr 2234
        pusha
2235
        mov     ecx, socket_mutex
2236
        call    mutex_unlock
2237
        popa
2238
 
3637 hidnplayr 2239
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax
3545 hidnplayr 2240
        ret
2241
 
2242
 
2243
;---------------------------------------------------
2244
;
2245
; SOCKET_ptr_to_num
2246
;
2247
; Get socket number by its address
2248
;
2249
; IN:  eax = socket ptr
2250
; OUT: eax = 0 on error, socket num otherwise
2251
;       ZF = set on error
2252
;
2253
;---------------------------------------------------
2254
align 4
2255
SOCKET_ptr_to_num:
2256
 
3556 hidnplayr 2257
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2258
 
2259
        call    SOCKET_check
2260
        jz      .error
2261
 
2262
        mov     eax, [eax + SOCKET.Number]
2263
 
3556 hidnplayr 2264
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2265
        ret
2266
 
2267
  .error:
3556 hidnplayr 2268
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2269
        ret
2270
 
2271
 
2272
;---------------------------------------------------
2273
;
2274
; SOCKET_check
2275
;
2276
; checks if the given value is really a socket ptr
2277
;
2278
; IN:  eax = socket ptr
2279
; OUT: eax = 0 on error, unchanged otherwise
2280
;       ZF = set on error
2281
;
2282
;---------------------------------------------------
2283
align 4
2284
SOCKET_check:
2285
 
3556 hidnplayr 2286
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2287
 
2288
        push    ebx
2289
        mov     ebx, net_sockets
2290
 
2291
  .next_socket:
2292
        mov     ebx, [ebx + SOCKET.NextPtr]
2293
        or      ebx, ebx
2294
        jz      .done
2295
        cmp     ebx, eax
2296
        jnz     .next_socket
2297
 
2298
  .done:
2299
        mov     eax, ebx
2300
        test    eax, eax
2301
        pop     ebx
2302
 
2303
        ret
2304
 
2305
 
2306
 
2307
;---------------------------------------------------
2308
;
2309
; SOCKET_check_owner
2310
;
2311
; checks if the caller application owns the socket
2312
;
2313
; IN:  eax = socket ptr
2314
; OUT:  ZF = true/false
2315
;
2316
;---------------------------------------------------
2317
align 4
2318
SOCKET_check_owner:
2319
 
3556 hidnplayr 2320
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2321
 
2322
        push    ebx
2323
        mov     ebx, [TASK_BASE]
2324
        mov     ebx, [ebx + TASKDATA.pid]
2325
        cmp     [eax + SOCKET.PID], ebx
2326
        pop      ebx
2327
 
2328
        ret
2329
 
2330
 
2331
 
2332
 
2333
;------------------------------------------------------
2334
;
2335
; SOCKET_process_end
2336
;
2337
; Kernel calls this function when a certain process ends
2338
; This function will check if the process had any open sockets
2339
; And update them accordingly
2340
;
2341
; IN:  edx = pid
2342
; OUT: /
2343
;
2344
;------------------------------------------------------
2345
align 4
2346
SOCKET_process_end:
2347
 
3648 hidnplayr 2348
        pushf
2349
        cli     ; FIXME
2350
 
3556 hidnplayr 2351
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2352
 
3647 hidnplayr 2353
        pusha
2354
        mov     ecx, socket_mutex
2355
        call    mutex_lock
2356
        popa
2357
 
3545 hidnplayr 2358
        push    ebx
2359
        mov     ebx, net_sockets
2360
 
2361
  .next_socket:
2362
        mov     ebx, [ebx + SOCKET.NextPtr]
2363
  .next_socket_test:
2364
        test    ebx, ebx
2365
        jz      .done
2366
 
2367
        cmp     [ebx + SOCKET.PID], edx
2368
        jne     .next_socket
2369
 
3556 hidnplayr 2370
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2371
 
2372
        mov     [ebx + SOCKET.PID], 0
2373
        mov     eax, ebx
2374
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2375
 
3545 hidnplayr 2376
        pusha
3648 hidnplayr 2377
        mov     ecx, socket_mutex
2378
        call    mutex_unlock
2379
        popa
2380
 
2381
        pusha
3652 hidnplayr 2382
        cmp     [eax + SOCKET.Domain], AF_INET4
2383
        jne     .free
2384
 
2385
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2386
        jne     .free
2387
 
2388
        call    TCP_close
2389
        jmp     .closed
2390
 
2391
  .free:
2392
        call    SOCKET_free
2393
 
2394
  .closed:
3545 hidnplayr 2395
        popa
3648 hidnplayr 2396
 
2397
        pusha
2398
        mov     ecx, socket_mutex
2399
        call    mutex_lock
2400
        popa
2401
 
3545 hidnplayr 2402
        jmp     .next_socket_test
2403
 
2404
  .done:
2405
        pop     ebx
2406
 
3647 hidnplayr 2407
        pusha
2408
        mov     ecx, socket_mutex
2409
        call    mutex_unlock
2410
        popa
2411
 
3648 hidnplayr 2412
        popf
2413
 
3545 hidnplayr 2414
        ret
2415
 
2416
 
2417
 
2418
 
2419
;-----------------------------------------------------------------
2420
;
2421
; SOCKET_is_connecting
2422
;
2423
;  IN:  eax = socket ptr
2424
;  OUT: /
2425
;
2426
;-----------------------------------------------------------------
2427
 
2428
align 4
2429
SOCKET_is_connecting:
2430
 
3556 hidnplayr 2431
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2432
 
2433
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2434
        or      [eax + SOCKET.options], SS_ISCONNECTING
2435
 
2436
        jmp     SOCKET_notify
2437
 
2438
 
2439
 
2440
;-----------------------------------------------------------------
2441
;
2442
; SOCKET_is_connected
2443
;
2444
;  IN:  eax = socket ptr
2445
;  OUT: /
2446
;
2447
;-----------------------------------------------------------------
2448
 
2449
align 4
2450
SOCKET_is_connected:
2451
 
3556 hidnplayr 2452
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2453
 
3674 hidnplayr 2454
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2455
        or      [eax + SOCKET.state], SS_ISCONNECTED
3545 hidnplayr 2456
 
2457
        jmp     SOCKET_notify
2458
 
2459
 
2460
 
2461
 
2462
;-----------------------------------------------------------------
2463
;
2464
; SOCKET_is_disconnecting
2465
;
2466
;  IN:  eax = socket ptr
2467
;  OUT: /
2468
;
2469
;-----------------------------------------------------------------
2470
 
2471
align 4
2472
SOCKET_is_disconnecting:
2473
 
3556 hidnplayr 2474
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2475
 
3674 hidnplayr 2476
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2477
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2478
 
2479
        jmp     SOCKET_notify
2480
 
2481
 
2482
 
2483
;-----------------------------------------------------------------
2484
;
2485
; SOCKET_is_disconnected
2486
;
2487
;  IN:  eax = socket ptr
2488
;  OUT: /
2489
;
2490
;-----------------------------------------------------------------
2491
 
2492
align 4
2493
SOCKET_is_disconnected:
2494
 
3556 hidnplayr 2495
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2496
 
3674 hidnplayr 2497
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2498
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2499
 
2500
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2501
        je      .tcp
2502
 
2503
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
2504
        je      .udp
2505
 
2506
        jmp     SOCKET_notify
2507
 
2508
  .tcp:
2509
  .udp:
2510
        mov     [eax + UDP_SOCKET.LocalPort], 0         ; UDP and TCP structs store localport at the same offset
2511
        mov     [eax + UDP_SOCKET.RemotePort], 0
2512
 
2513
        jmp     SOCKET_notify
2514
 
2515
 
2516
;-----------------------------------------------------------------
2517
;
2518
; SOCKET_cant_recv_more
2519
;
2520
;  IN:  eax = socket ptr
2521
;  OUT: /
2522
;
2523
;-----------------------------------------------------------------
2524
 
2525
align 4
2526
SOCKET_cant_recv_more:
2527
 
3556 hidnplayr 2528
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2529
 
3674 hidnplayr 2530
        or      [eax + SOCKET.state], SS_CANTRCVMORE
3545 hidnplayr 2531
 
3565 hidnplayr 2532
        call    SOCKET_notify
2533
 
3545 hidnplayr 2534
        ret
2535
 
2536
 
2537
 
2538
;-----------------------------------------------------------------
2539
;
2540
; SOCKET_cant_send_more
2541
;
2542
;  IN:  eax = socket ptr
2543
;  OUT: /
2544
;
2545
;-----------------------------------------------------------------
2546
 
2547
align 4
2548
SOCKET_cant_send_more:
2549
 
3556 hidnplayr 2550
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2551
 
3674 hidnplayr 2552
        or      [eax + SOCKET.state], SS_CANTSENDMORE
3658 hidnplayr 2553
        mov     [eax + SOCKET.snd_proc], .notconn
3545 hidnplayr 2554
 
3565 hidnplayr 2555
        call    SOCKET_notify
2556
 
3658 hidnplayr 2557
        ret
2558
 
2559
  .notconn:
3673 hidnplayr 2560
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2561
        mov     dword[esp+32], -1
3545 hidnplayr 2562
        ret