Subversion Repositories Kolibri OS

Rev

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