Subversion Repositories Kolibri OS

Rev

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