Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3555 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
9
;;     and Clevermouse.                                            ;;
10
;;                                                                 ;;
11
;;       Based on code by mike.dld                                 ;;
12
;;                                                                 ;;
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 hidnplayr 17
 
593 mikedld 18
$Revision: 3725 $
19
 
2434 Serge 20
struct  SOCKET
3555 Serge 21
 
22
        NextPtr                 dd ? ; pointer to next socket in list
23
        PrevPtr                 dd ? ; pointer to previous socket in list
24
        Number                  dd ? ; socket number
25
 
26
        mutex                   MUTEX
27
 
28
        PID                     dd ? ; process ID
29
        TID                     dd ? ; thread ID
30
        Domain                  dd ? ; INET/LOCAL/..
31
        Type                    dd ? ; RAW/STREAM/DGRAP
32
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
33
        errorcode               dd ?
34
        device                  dd ? ; driver pointer, socket pointer if it's an LOCAL socket
35
 
36
        options                 dd ?
37
        state                   dd ?
38
        backlog                 dw ? ; how many incoming connections that can be queued
39
 
40
        snd_proc                dd ?
41
        rcv_proc                dd ?
42
 
922 mikedld 43
ends
593 mikedld 44
 
3555 Serge 45
struct  IP_SOCKET               SOCKET
261 hidnplayr 46
 
3555 Serge 47
        LocalIP                 rd 4 ; network byte order
48
        RemoteIP                rd 4 ; network byte order
261 hidnplayr 49
 
3555 Serge 50
ends
51
 
52
struct  TCP_SOCKET              IP_SOCKET
53
 
54
        LocalPort               dw ? ; network byte order
55
        RemotePort              dw ? ; network byte order
56
 
57
        t_state                 dd ? ; TCB state
58
        t_rxtshift              db ?
59
                                rb 3 ; align
60
        t_rxtcur                dd ?
61
        t_dupacks               dd ?
62
        t_maxseg                dd ?
63
        t_force                 dd ?
64
        t_flags                 dd ?
65
 
66
;---------------
67
; RFC783 page 21
68
 
69
; send sequence
70
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
71
        SND_NXT                 dd ? ; next send sequence number to use
72
        SND_UP                  dd ? ; urgent pointer
73
        SND_WL1                 dd ? ; window minus one
74
        SND_WL2                 dd ? ;
75
        ISS                     dd ? ; initial send sequence number
76
        SND_WND                 dd ? ; send window
77
 
78
; receive sequence
79
        RCV_WND                 dd ? ; receive window
80
        RCV_NXT                 dd ? ; next receive sequence number to use
81
        RCV_UP                  dd ? ; urgent pointer
82
        IRS                     dd ? ; initial receive sequence number
83
 
84
;---------------------
85
; Additional variables
86
 
87
; receive variables
88
        RCV_ADV                 dd ?
89
 
90
; retransmit variables
91
        SND_MAX                 dd ?
92
 
93
; congestion control
94
        SND_CWND                dd ?
95
        SND_SSTHRESH            dd ?
96
 
97
;----------------------
98
; Transmit timing stuff
99
        t_idle                  dd ?
100
        t_rtt                   dd ?
101
        t_rtseq                 dd ?
102
        t_srtt                  dd ?
103
        t_rttvar                dd ?
104
        t_rttmin                dd ?
105
        max_sndwnd              dd ?
106
 
107
;-----------------
108
; Out-of-band data
109
        t_oobflags              dd ?
110
        t_iobc                  dd ?
111
        t_softerror             dd ?
112
 
113
 
114
;---------
115
; RFC 1323                              ; the order of next 4 elements may not change
116
 
117
        SND_SCALE               db ?
118
        RCV_SCALE               db ?
119
        requested_s_scale       db ?
120
        request_r_scale         db ?
121
 
122
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
123
        ts_recent_age           dd ?
124
        last_ack_sent           dd ?
125
 
126
 
127
;-------
128
; Timers
3626 Serge 129
        timer_flags             dd ?
3555 Serge 130
        timer_retransmission    dd ? ; rexmt
131
        timer_persist           dd ?
132
        timer_keepalive         dd ? ; keepalive/syn timeout
133
        timer_timed_wait        dd ? ; also used as 2msl timer
134
 
135
; extra
136
 
137
        ts_ecr                  dd ? ; timestamp echo reply
138
        ts_val                  dd ?
139
 
140
        seg_next                dd ? ; re-assembly queue
141
 
142
        temp_bits               db ?
143
                                rb 3 ; align
144
 
145
ends
146
 
147
struct  UDP_SOCKET              IP_SOCKET
148
 
149
        LocalPort               dw ? ; network byte order
150
        RemotePort              dw ? ; network byte order
151
        firstpacket             db ?
152
 
153
ends
154
 
155
 
156
struct  ICMP_SOCKET             IP_SOCKET
157
 
158
        Identifier              dw ?
159
 
160
ends
161
 
162
 
163
struct  RING_BUFFER
164
 
165
        mutex                   MUTEX
166
        start_ptr               dd ? ; Pointer to start of buffer
167
        end_ptr                 dd ? ; pointer to end of buffer
168
        read_ptr                dd ? ; Read pointer
169
        write_ptr               dd ? ; Write pointer
170
        size                    dd ? ; Number of bytes buffered
171
 
172
ends
173
 
174
struct  STREAM_SOCKET           TCP_SOCKET
175
 
176
        rcv                     RING_BUFFER
177
        snd                     RING_BUFFER
178
 
179
ends
180
 
181
struct  socket_queue_entry
182
 
183
        data_ptr                dd ?
184
        buf_ptr                 dd ?
185
        data_size               dd ?
186
 
187
ends
188
 
189
 
190
SOCKETBUFFSIZE          = 4096     ; in bytes
191
 
192
SOCKET_QUEUE_SIZE       = 10       ; maximum number of incoming packets queued for 1 socket
193
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
194
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
195
 
1154 clevermous 196
uglobal
3725 Serge 197
align 4
198
 
3555 Serge 199
        net_sockets     rd 4
200
        last_socket_num dd ?
201
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
202
        last_TCP_port   dw ? ;
3725 Serge 203
        socket_mutex    MUTEX
204
 
1154 clevermous 205
endg
206
 
3555 Serge 207
 
208
;-----------------------------------------------------------------
209
;
210
; SOCKET_init
211
;
212
;-----------------------------------------------------------------
213
macro   SOCKET_init {
214
 
215
        xor     eax, eax
216
        mov     edi, net_sockets
217
        mov     ecx, 5
3725 Serge 218
        rep stosd
3555 Serge 219
 
220
       @@:
221
        pseudo_random eax
3626 Serge 222
        cmp     ax, EPHEMERAL_PORT_MIN
3555 Serge 223
        jb      @r
3626 Serge 224
        cmp     ax, EPHEMERAL_PORT_MAX
3555 Serge 225
        ja      @r
226
        xchg    al, ah
227
        mov     [last_UDP_port], ax
228
 
229
       @@:
230
        pseudo_random eax
3626 Serge 231
        cmp     ax, EPHEMERAL_PORT_MIN
3555 Serge 232
        jb      @r
3626 Serge 233
        cmp     ax, EPHEMERAL_PORT_MAX
3555 Serge 234
        ja      @r
235
        xchg    al, ah
236
        mov     [last_TCP_port], ax
237
 
3725 Serge 238
        mov     ecx, socket_mutex
239
        call    mutex_init
240
 
3555 Serge 241
}
242
 
243
;-----------------------------------------------------------------
244
;
245
; Socket API (function 74)
246
;
247
;-----------------------------------------------------------------
1154 clevermous 248
align 4
3555 Serge 249
sys_socket:
1154 clevermous 250
 
3725 Serge 251
        mov     dword[esp+20], 0        ; Set error code to 0
252
 
3555 Serge 253
        cmp     ebx, 255
254
        jz      SOCKET_debug
255
 
256
        cmp     ebx, .number
3725 Serge 257
        ja      .error
3555 Serge 258
        jmp     dword [.table + 4*ebx]
259
 
260
  .table:
261
        dd      SOCKET_open     ; 0
262
        dd      SOCKET_close    ; 1
263
        dd      SOCKET_bind     ; 2
264
        dd      SOCKET_listen   ; 3
265
        dd      SOCKET_connect  ; 4
266
        dd      SOCKET_accept   ; 5
267
        dd      SOCKET_send     ; 6
268
        dd      SOCKET_receive  ; 7
269
        dd      SOCKET_set_opt  ; 8
270
        dd      SOCKET_get_opt  ; 9
271
        dd      SOCKET_pair     ; 10
272
  .number = ($ - .table) / 4 - 1
273
 
3725 Serge 274
  .error:
275
        mov     dword[esp+32], -1
276
        mov     dword[esp+20], EINVAL
3555 Serge 277
 
278
        ret
279
 
280
;-----------------------------------------------------------------
922 mikedld 281
;
3555 Serge 282
; SOCKET_open
283
;
284
;  IN:  domain in ecx
285
;       type in edx
286
;       protocol in esi
287
;  OUT: eax is socket num, -1 on error
288
;
289
;-----------------------------------------------------------------
290
align 4
291
SOCKET_open:
907 mikedld 292
 
3589 Serge 293
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
3555 Serge 294
 
295
        push    ecx edx esi
296
        call    SOCKET_alloc
297
        pop     esi edx ecx
3725 Serge 298
        jz      .nobuffs
3555 Serge 299
 
300
        mov     [esp+32], edi                   ; return socketnumber
3589 Serge 301
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
3555 Serge 302
 
3725 Serge 303
        test    edx, SO_NONBLOCK
304
        jz      @f
305
        or      [eax + SOCKET.options], SO_NONBLOCK
306
        and     edx, not SO_NONBLOCK
307
  @@:
3555 Serge 308
 
309
        mov     [eax + SOCKET.Domain], ecx
310
        mov     [eax + SOCKET.Type], edx
311
        mov     [eax + SOCKET.Protocol], esi
312
 
313
        cmp     ecx, AF_INET4
314
        jne     .no_inet4
315
 
316
        cmp     edx, SOCK_DGRAM
317
        je      .udp
318
 
319
        cmp     edx, SOCK_STREAM
320
        je      .tcp
321
 
322
        cmp     edx, SOCK_RAW
323
        je      .raw
324
 
325
  .no_inet4:
326
        cmp     ecx, AF_PPP
327
        jne     .no_ppp
328
 
329
        cmp     esi, PPP_PROTO_ETHERNET
330
        je      .pppoe
331
 
332
  .no_ppp:
3725 Serge 333
  .unsupported:
334
        push    eax
335
        call    SOCKET_free
336
        pop     eax
337
        mov     dword[esp+20], EOPNOTSUPP
338
        mov     dword[esp+32], -1
3555 Serge 339
        ret
340
 
3725 Serge 341
  .nobuffs:
342
        mov     dword[esp+20], ENOBUFS
343
        mov     dword[esp+32], -1
344
        ret
345
 
3555 Serge 346
  .raw:
347
        test    esi, esi       ; IP_PROTO_IP
3725 Serge 348
        jz      .raw_ip
3555 Serge 349
 
350
        cmp     esi, IP_PROTO_ICMP
3725 Serge 351
        je      .raw_icmp
3555 Serge 352
 
3725 Serge 353
        jmp     .unsupported
3555 Serge 354
 
355
align 4
356
  .udp:
357
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
358
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
359
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
360
        ret
361
 
362
align 4
363
  .tcp:
364
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
365
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
366
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
367
 
368
        TCP_init_socket eax
369
        ret
370
 
371
 
372
align 4
3725 Serge 373
  .raw_ip:
3555 Serge 374
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
375
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
376
        ret
377
 
378
 
379
align 4
3725 Serge 380
  .raw_icmp:
3555 Serge 381
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
382
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
383
        ret
384
 
385
align 4
386
  .pppoe:
2434 Serge 387
        push    eax
3555 Serge 388
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
2434 Serge 389
        pop     eax
907 mikedld 390
 
3555 Serge 391
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
392
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
393
        ret
394
 
395
 
396
;-----------------------------------------------------------------
397
;
398
; SOCKET_bind
399
;
400
;  IN:  socket number in ecx
401
;       pointer to sockaddr struct in edx
402
;       length of that struct in esi
403
;  OUT: 0 on success
404
;
405
;-----------------------------------------------------------------
406
align 4
407
SOCKET_bind:
408
 
3589 Serge 409
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3555 Serge 410
 
411
        call    SOCKET_num_to_ptr
3725 Serge 412
        jz      .invalid
3555 Serge 413
 
414
        cmp     esi, 2
3725 Serge 415
        jb      .invalid
3555 Serge 416
 
417
        cmp     word [edx], AF_INET4
418
        je      .af_inet4
419
 
420
        cmp     word [edx], AF_LOCAL
421
        je      .af_local
422
 
3725 Serge 423
  .notsupp:
424
        mov     dword[esp+20], EOPNOTSUPP
425
        mov     dword[esp+32], -1
426
        ret
3555 Serge 427
 
3725 Serge 428
  .invalid:
429
        mov     dword[esp+20], EINVAL
430
        mov     dword[esp+32], -1
431
        ret
432
 
3555 Serge 433
  .af_local:
434
        ; TODO: write code here
3725 Serge 435
        mov     dword[esp+32], 0
3555 Serge 436
        ret
437
 
438
  .af_inet4:
439
        cmp     esi, 6
3725 Serge 440
        jb      .invalid
3555 Serge 441
 
442
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
443
        je      .udp
444
 
445
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
446
        je      .tcp
447
 
3725 Serge 448
        jmp     .notsupp
3555 Serge 449
 
450
  .tcp:
451
  .udp:
3725 Serge 452
        mov     ebx, [edx + 4]                  ; First, fill in the IP
3555 Serge 453
        test    ebx, ebx                        ; If IP is 0, use default
454
        jnz     @f
3626 Serge 455
        mov     ebx, [IP_LIST + 4]      ;;;;; FIXME !i!i!i
3555 Serge 456
       @@:
457
        mov     [eax + IP_SOCKET.LocalIP], ebx
458
 
459
        mov     bx, [edx + 2]                   ; Now fill in the local port if it's still available
460
        call    SOCKET_check_port
3725 Serge 461
        jz      .addrinuse                      ; ZF is set by socket_check_port, on error
3555 Serge 462
 
3589 Serge 463
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3555 Serge 464
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
465
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
466
 
3725 Serge 467
        mov     dword[esp+32], 0
3555 Serge 468
        ret
469
 
3725 Serge 470
  .addrinuse:
471
        mov     dword[esp+32], -1
472
        mov     dword[esp+20], EADDRINUSE
473
        ret
3555 Serge 474
 
475
 
476
 
3725 Serge 477
 
3555 Serge 478
;-----------------------------------------------------------------
479
;
480
; SOCKET_connect
481
;
482
;  IN:  socket number in ecx
483
;       pointer to sockaddr struct in edx
484
;       length of that struct in esi
485
;  OUT: 0 on success
486
;
487
;-----------------------------------------------------------------
488
align 4
489
SOCKET_connect:
490
 
3589 Serge 491
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3555 Serge 492
 
493
        call    SOCKET_num_to_ptr
3725 Serge 494
        jz      .invalid
3555 Serge 495
 
496
        cmp     esi, 8
3725 Serge 497
        jb      .invalid
3555 Serge 498
 
499
        cmp     word [edx], AF_INET4
500
        je      .af_inet4
501
 
3725 Serge 502
  .notsupp:
503
        mov     dword[esp+20], EOPNOTSUPP
504
        mov     dword[esp+32], -1
505
        ret
3555 Serge 506
 
3725 Serge 507
  .invalid:
508
        mov     dword[esp+20], EINVAL
509
        mov     dword[esp+32], -1
510
        ret
511
 
3555 Serge 512
  .af_inet4:
513
        cmp     [eax + IP_SOCKET.LocalIP], 0
514
        jne     @f
3626 Serge 515
        push    [IP_LIST + 4]                               ; FIXME !i!i!i!
3555 Serge 516
        pop     [eax + IP_SOCKET.LocalIP]
517
       @@:
518
 
519
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
520
        je      .udp
521
 
522
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
523
        je      .tcp
524
 
525
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
526
        je      .ip
527
 
528
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
529
        je      .ip
530
 
3725 Serge 531
        jmp     .notsupp
3555 Serge 532
 
533
align 4
534
  .udp:
535
        pusha
536
        lea     ecx, [eax + SOCKET.mutex]
537
        call    mutex_lock
538
        popa
539
 
540
        pushw   [edx + 2]
541
        pop     [eax + UDP_SOCKET.RemotePort]
542
 
543
        pushd   [edx + 4]
544
        pop     [eax + IP_SOCKET.RemoteIP]
545
 
546
        cmp     [eax + UDP_SOCKET.LocalPort], 0
547
        jne     @f
548
        call    SOCKET_find_port
549
       @@:
550
 
551
        mov     [eax + UDP_SOCKET.firstpacket], 0
552
 
553
        push    eax
554
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
555
        pop     eax
556
 
557
        lea     ecx, [eax + SOCKET.mutex]
558
        call    mutex_unlock
559
 
3725 Serge 560
        mov     dword[esp+32], 0
3555 Serge 561
        ret
562
 
563
align 4
564
  .tcp:
565
        pusha
566
        lea     ecx, [eax + SOCKET.mutex]
567
        call    mutex_lock
568
        popa
569
 
570
        pushw   [edx + 2]
571
        pop     [eax + TCP_SOCKET.RemotePort]
572
 
573
        pushd   [edx + 4]
574
        pop     [eax + IP_SOCKET.RemoteIP]
575
 
576
        cmp     [eax + TCP_SOCKET.LocalPort], 0
577
        jne     @f
578
        call    SOCKET_find_port
579
       @@:
580
 
581
        mov     [eax + TCP_SOCKET.timer_persist], 0
582
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
583
 
584
        push    [TCP_sequence_num]
585
        add     [TCP_sequence_num], 6400
586
        pop     [eax + TCP_SOCKET.ISS]
587
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
588
 
589
        TCP_sendseqinit eax
590
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
591
 
2434 Serge 592
        mov     ebx, eax
3555 Serge 593
        lea     eax, [ebx + STREAM_SOCKET.snd]
3725 Serge 594
        call    SOCKET_ring_create              ; TODO: check if memory was available or not
3555 Serge 595
 
596
        lea     eax, [ebx + STREAM_SOCKET.rcv]
3725 Serge 597
        call    SOCKET_ring_create              ; TODO: same here
3555 Serge 598
 
599
        pusha
600
        lea     ecx, [ebx + SOCKET.mutex]
601
        call    mutex_unlock
602
        popa
603
 
3725 Serge 604
        push    ebx
2434 Serge 605
        mov     eax, ebx
3555 Serge 606
        call    TCP_output
3725 Serge 607
        pop     eax
2130 serge 608
 
3725 Serge 609
  .block:
610
        test    [eax + SOCKET.options], SO_NONBLOCK
611
        jz      .loop
3555 Serge 612
 
3725 Serge 613
        mov     dword[esp+20], EWOULDBLOCK
614
        mov     dword[esp+32], -1
3555 Serge 615
        ret
616
 
3725 Serge 617
  .loop:
618
        cmp     [eax + TCP_SOCKET.t_state], TCPS_CLOSED
619
        je      .fail
620
        cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
621
        je      .established
622
        ja      .fail
623
 
624
        call    SOCKET_block
625
        jmp     .loop
626
 
627
  .fail:
628
        mov     eax, [eax + SOCKET.errorcode]
629
        mov     [esp+20], eax
630
        mov     dword[esp+32], -1
631
        ret
632
 
633
  .established:
634
        mov     dword[esp+32], 0
635
        ret
636
 
637
 
3555 Serge 638
align 4
639
  .ip:
640
        pusha
641
        lea     ecx, [eax + SOCKET.mutex]
642
        call    mutex_lock
643
        popa
644
 
645
        pushd   [edx + 4]
646
        pop     [eax + IP_SOCKET.RemoteIP]
647
 
648
        push    eax
649
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
650
        pop     eax
651
 
652
        lea     ecx, [eax + SOCKET.mutex]
653
        call    mutex_unlock
654
 
3725 Serge 655
        mov     dword[esp+32], 0
3555 Serge 656
        ret
657
 
658
 
659
;-----------------------------------------------------------------
660
;
661
; SOCKET_listen
662
;
663
;  IN:  socket number in ecx
664
;       backlog in edx
665
;  OUT: eax is socket num, -1 on error
666
;
667
;-----------------------------------------------------------------
668
align 4
669
SOCKET_listen:
670
 
3589 Serge 671
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3555 Serge 672
 
673
        call    SOCKET_num_to_ptr
3725 Serge 674
        jz      .invalid
3555 Serge 675
 
676
        cmp     [eax + SOCKET.Domain], AF_INET4
3725 Serge 677
        jne     .notsupp
3555 Serge 678
 
679
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3725 Serge 680
        jne     .invalid
3555 Serge 681
 
682
        cmp     [eax + TCP_SOCKET.LocalPort], 0
3725 Serge 683
        je      .already
3555 Serge 684
 
685
        cmp     [eax + IP_SOCKET.LocalIP], 0
686
        jne     @f
3626 Serge 687
        push    [IP_LIST + 4]           ;;; fixme!!!!
3555 Serge 688
        pop     [eax + IP_SOCKET.LocalIP]
689
       @@:
690
 
691
        cmp     edx, MAX_backlog
692
        jbe     @f
693
        mov     edx, MAX_backlog
694
       @@:
695
 
696
        mov     [eax + SOCKET.backlog], dx
697
        or      [eax + SOCKET.options], SO_ACCEPTCON
698
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
699
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
700
 
701
        push    eax
702
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
703
        pop     eax
704
 
3725 Serge 705
        mov     dword[esp+32], 0
706
        ret
3555 Serge 707
 
3725 Serge 708
  .notsupp:
709
        mov     dword[esp+20], EOPNOTSUPP
710
        mov     dword[esp+32], -1
3555 Serge 711
        ret
712
 
3725 Serge 713
  .invalid:
714
        mov     dword[esp+20], EINVAL
715
        mov     dword[esp+32], -1
716
        ret
3555 Serge 717
 
3725 Serge 718
  .already:
719
        mov     dword[esp+20], EALREADY
720
        mov     dword[esp+32], -1
721
        ret
722
 
723
 
3555 Serge 724
;-----------------------------------------------------------------
725
;
726
; SOCKET_accept
727
;
728
;  IN:  socket number in ecx
729
;       addr in edx
730
;       addrlen in esi
731
;  OUT: eax is socket num, -1 on error
732
;
733
;-----------------------------------------------------------------
734
align 4
735
SOCKET_accept:
736
 
3589 Serge 737
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3555 Serge 738
 
739
        call    SOCKET_num_to_ptr
3725 Serge 740
        jz      .invalid
3555 Serge 741
 
742
        test    [eax + SOCKET.options], SO_ACCEPTCON
3725 Serge 743
        jz      .invalid
3555 Serge 744
 
745
        cmp     [eax + SOCKET.Domain], AF_INET4
3725 Serge 746
        jne     .notsupp
3555 Serge 747
 
748
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3725 Serge 749
        jne     .invalid
3555 Serge 750
 
751
  .loop:
752
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
753
 
754
; Ok, we got a socket ptr
755
        mov     eax, [esi]
756
 
3725 Serge 757
; Convert it to a socket number
758
        call    SOCKET_ptr_to_num
759
        jz      .invalid        ; FIXME ?
760
 
3555 Serge 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
3725 Serge 772
        jnz     .wouldblock
3555 Serge 773
 
774
        call    SOCKET_block
775
        jmp     .loop
776
 
3725 Serge 777
  .wouldblock:
778
        mov     dword[esp+20], EWOULDBLOCK
779
        mov     dword[esp+32], -1
780
        ret
781
 
782
  .invalid:
783
        mov     dword[esp+20], EINVAL
784
        mov     dword[esp+32], -1
785
        ret
786
 
787
  .notsupp:
788
        mov     dword[esp+20], EOPNOTSUPP
789
        mov     dword[esp+32], -1
790
        ret
791
 
3555 Serge 792
;-----------------------------------------------------------------
793
;
794
; SOCKET_close
795
;
796
;  IN:  socket number in ecx
797
;  OUT: eax is socket num, -1 on error
798
;
799
;-----------------------------------------------------------------
800
align 4
801
SOCKET_close:
802
 
3589 Serge 803
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3555 Serge 804
 
805
        call    SOCKET_num_to_ptr
3725 Serge 806
        jz      .invalid
3555 Serge 807
 
3725 Serge 808
        mov     dword[esp+32], 0                                ; The socket exists, so we will succeed in closing it.
3555 Serge 809
 
810
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
811
 
812
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
2434 Serge 813
        jz      @f
3555 Serge 814
        call    SOCKET_notify.unblock                           ; Unblock it.
815
  @@:
907 mikedld 816
 
3555 Serge 817
        cmp     [eax + SOCKET.Domain], AF_INET4
818
        jne     .free
819
 
820
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
821
        je      .tcp
822
 
823
  .free:
824
        call    SOCKET_free
825
        ret
826
 
827
  .tcp:
828
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
829
        jb      .free
830
 
831
        call    TCP_usrclosed
832
        call    TCP_output      ;;;; Fixme: is this nescessary??
3725 Serge 833
        call    SOCKET_free
3555 Serge 834
 
835
        ret
836
 
837
 
3725 Serge 838
  .invalid:
839
        mov     dword[esp+20], EINVAL
840
        mov     dword[esp+32], -1
841
        ret
842
 
843
 
3555 Serge 844
;-----------------------------------------------------------------
845
;
846
; SOCKET_receive
847
;
848
;  IN:  socket number in ecx
849
;       addr to buffer in edx
850
;       length of buffer in esi
851
;       flags in edi
852
;  OUT: eax is number of bytes copied, -1 on error
853
;
854
;-----------------------------------------------------------------
855
align 4
856
SOCKET_receive:
857
 
3589 Serge 858
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3555 Serge 859
 
860
        call    SOCKET_num_to_ptr
3725 Serge 861
        jz      .invalid
3555 Serge 862
 
3725 Serge 863
  .loop:
864
        push    edi
3589 Serge 865
        call    [eax + SOCKET.rcv_proc]
3725 Serge 866
        pop     edi
3555 Serge 867
 
3725 Serge 868
        cmp     ebx, EWOULDBLOCK
869
        jne     .return
870
 
871
        test    edi, MSG_DONTWAIT
872
        jnz     .return_err
873
 
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:
887
        mov     [esp+20], ebx
3589 Serge 888
        mov     [esp+32], eax
889
        ret
3555 Serge 890
 
3589 Serge 891
 
3725 Serge 892
 
893
 
894
 
3555 Serge 895
align 4
896
SOCKET_receive_dgram:
897
 
3589 Serge 898
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3555 Serge 899
 
3725 Serge 900
        mov     ebx, esi                                        ; bufferlength
3555 Serge 901
 
3725 Serge 902
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
3555 Serge 903
        mov     ecx, [esi + socket_queue_entry.data_size]
3589 Serge 904
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3555 Serge 905
 
3725 Serge 906
        cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
3555 Serge 907
        ja      .too_small
908
 
3589 Serge 909
        push    ecx
3555 Serge 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]
3589 Serge 912
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3555 Serge 913
 
3725 Serge 914
; copy the data from kernel buffer to application buffer
915
        mov     edi, edx                                        ; bufferaddr
3555 Serge 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
3725 Serge 926
        rep movsd
3555 Serge 927
  .nd:
928
 
3725 Serge 929
        call    kernel_free                                     ; free kernel buffer
930
        pop     eax                                             ; return number of bytes copied to application
931
        xor     ebx, ebx
3555 Serge 932
        ret
933
 
934
  .too_small:
3589 Serge 935
        mov     eax, -1
3725 Serge 936
        push    EMSGSIZE
937
        pop     ebx
3589 Serge 938
        ret
3555 Serge 939
 
3725 Serge 940
  .wouldblock:
941
        push    EWOULDBLOCK
942
        pop     ebx
943
        ret
3555 Serge 944
 
945
 
946
 
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
2434 Serge 955
        mov     ebx, [TASK_BASE]
956
        mov     ebx, [ebx + TASKDATA.pid]
957
        mov     [eax + SOCKET.PID], ebx
3725 Serge 958
        mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
3555 Serge 959
      @@:
907 mikedld 960
 
3555 Serge 961
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
922 mikedld 962
 
3725 Serge 963
; ... continue to SOCKET_receive_stream
964
 
3555 Serge 965
align 4
966
SOCKET_receive_stream:
922 mikedld 967
 
3589 Serge 968
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3555 Serge 969
 
3725 Serge 970
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
971
        je      .wouldblock
972
 
973
        test    edi, MSG_PEEK
974
        jnz     .peek
975
 
3555 Serge 976
        mov     ecx, esi
977
        mov     edi, edx
978
        xor     edx, edx
979
 
980
        add     eax, STREAM_SOCKET.rcv
3725 Serge 981
        call    SOCKET_ring_read                                ; copy data from kernel buffer to application buffer
982
        call    SOCKET_ring_free                                ; free read memory
3555 Serge 983
 
3725 Serge 984
        mov     eax, ecx                                        ; return number of bytes copied
985
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
2434 Serge 986
        ret
907 mikedld 987
 
3725 Serge 988
  .wouldblock:
989
        push    EWOULDBLOCK
990
        pop     ebx
991
        ret
992
 
3555 Serge 993
  .peek:
3589 Serge 994
        mov     eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3725 Serge 995
        xor     ebx, ebx
3555 Serge 996
        ret
997
 
998
 
999
;-----------------------------------------------------------------
922 mikedld 1000
;
3555 Serge 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:
907 mikedld 1013
 
3589 Serge 1014
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
907 mikedld 1015
 
3555 Serge 1016
        call    SOCKET_num_to_ptr
3725 Serge 1017
        jz      .invalid
3555 Serge 1018
 
1019
        mov     ecx, esi
1020
        mov     esi, edx
1021
 
1022
        jmp     [eax + SOCKET.snd_proc]
1023
 
3725 Serge 1024
  .invalid:
1025
        mov     dword[esp+20], EINVAL
1026
        mov     dword[esp+32], -1
1027
        ret
3555 Serge 1028
 
3725 Serge 1029
 
3555 Serge 1030
align 4
1031
SOCKET_send_udp:
1032
 
3589 Serge 1033
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3555 Serge 1034
 
1035
        mov     [esp+32], ecx
1036
        call    UDP_output
1037
        cmp     eax, -1
3725 Serge 1038
        je      .error
3555 Serge 1039
        ret
1040
 
3725 Serge 1041
  .error:
1042
        mov     dword[esp+32], -1
1043
        mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
1044
        ret
3555 Serge 1045
 
3725 Serge 1046
 
3555 Serge 1047
align 4
1048
SOCKET_send_tcp:
1049
 
3589 Serge 1050
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3555 Serge 1051
 
2434 Serge 1052
        push    eax
3555 Serge 1053
        add     eax, STREAM_SOCKET.snd
1054
        call    SOCKET_ring_write
2434 Serge 1055
        pop     eax
907 mikedld 1056
 
3555 Serge 1057
        mov     [esp+32], ecx
3725 Serge 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]
1063
        mov     [esp+20], eax
2434 Serge 1064
        ret
907 mikedld 1065
 
3555 Serge 1066
 
1067
align 4
1068
SOCKET_send_ip:
1069
 
3589 Serge 1070
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3555 Serge 1071
 
1072
        mov     [esp+32], ecx
3725 Serge 1073
        call    IPv4_output_raw         ; FIXME: IPv4_output_raw should return error codes!
3555 Serge 1074
        cmp     eax, -1
3725 Serge 1075
        je      .error
2434 Serge 1076
        ret
907 mikedld 1077
 
3725 Serge 1078
  .error:
1079
        mov     dword[esp+32], -1
1080
        mov     dword[esp+20], EMSGSIZE
1081
        ret
3555 Serge 1082
 
3725 Serge 1083
 
3555 Serge 1084
align 4
1085
SOCKET_send_icmp:
1086
 
3589 Serge 1087
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3555 Serge 1088
 
1089
        mov     [esp+32], ecx
3725 Serge 1090
        call    ICMP_output_raw         ; FIXME: errorcodes
3555 Serge 1091
        cmp     eax, -1
3725 Serge 1092
        je      .error
3555 Serge 1093
        ret
1094
 
3725 Serge 1095
  .error:
1096
        mov     dword[esp+32], -1
1097
        mov     dword[esp+20], EMSGSIZE
1098
        ret
3555 Serge 1099
 
3725 Serge 1100
 
3555 Serge 1101
align 4
1102
SOCKET_send_pppoe:
1103
 
3589 Serge 1104
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3555 Serge 1105
 
1106
        mov     [esp+32], ecx
1107
        mov     ebx, [eax + SOCKET.device]
1108
 
3725 Serge 1109
        call    PPPoE_discovery_output  ; FIXME: errorcodes
3555 Serge 1110
        cmp     eax, -1
3725 Serge 1111
        je      .error
3555 Serge 1112
        ret
1113
 
3725 Serge 1114
  .error:
1115
        mov     dword[esp+32], -1
1116
        mov     dword[esp+20], EMSGSIZE
1117
        ret
3555 Serge 1118
 
1119
 
3725 Serge 1120
 
3555 Serge 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
 
3589 Serge 1139
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3555 Serge 1140
 
1141
        ; get the other side's socket and check if it still exists
1142
        mov     eax, [eax + SOCKET.device]
1143
        call    SOCKET_check
3725 Serge 1144
        jz      .invalid
3555 Serge 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
 
3725 Serge 1160
  .invalid:
1161
        mov     dword[esp+32], -1
1162
        mov     dword[esp+20], EINVAL
1163
        ret
3555 Serge 1164
 
3725 Serge 1165
 
3555 Serge 1166
;-----------------------------------------------------------------
922 mikedld 1167
;
3555 Serge 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:
922 mikedld 1182
 
3589 Serge 1183
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
922 mikedld 1184
 
3555 Serge 1185
        call    SOCKET_num_to_ptr
3725 Serge 1186
        jz      .invalid
3555 Serge 1187
 
1188
        cmp     dword [edx], IP_PROTO_TCP
3725 Serge 1189
        jne     .invalid
3555 Serge 1190
        cmp     dword [edx+4], -2
1191
        je      @f
1192
        cmp     dword [edx+4], -3
3725 Serge 1193
        jne     .invalid
3555 Serge 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
2434 Serge 1216
        ret
907 mikedld 1217
 
3725 Serge 1218
  .invalid:
1219
        mov     dword[esp+32], -1
1220
        mov     dword[esp+20], EINVAL
1221
        ret
3555 Serge 1222
 
1223
 
3725 Serge 1224
 
3555 Serge 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
 
3589 Serge 1238
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3555 Serge 1239
 
1240
        call    SOCKET_num_to_ptr
3725 Serge 1241
        jz      .invalid
3555 Serge 1242
 
1243
        cmp     dword [edx], SOL_SOCKET
3725 Serge 1244
        jne     .invalid
3555 Serge 1245
 
1246
        cmp     dword [edx+4], SO_BINDTODEVICE
1247
        je      .bind
1248
 
3725 Serge 1249
  .invalid:
1250
        mov     dword[esp+32], -1
1251
        mov     dword[esp+20], EINVAL
1252
        ret
3555 Serge 1253
 
1254
  .bind:
3725 Serge 1255
        cmp     dword[edx+8], 0
3555 Serge 1256
        je      .unbind
1257
 
3725 Serge 1258
        movzx   edx, byte[edx + 9]
3626 Serge 1259
        cmp     edx, NET_DEVICES_MAX
3725 Serge 1260
        ja      .invalid
3555 Serge 1261
 
1262
        mov     edx, [NET_DRV_LIST + 4*edx]
1263
        test    edx, edx
3725 Serge 1264
        jz      .already
3555 Serge 1265
        mov     [eax + SOCKET.device], edx
1266
 
3589 Serge 1267
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
3555 Serge 1268
 
3725 Serge 1269
        mov     dword[esp+32], 0        ; success!
2434 Serge 1270
        ret
907 mikedld 1271
 
3555 Serge 1272
  .unbind:
1273
        mov     [eax + SOCKET.device], 0
1274
 
3725 Serge 1275
        mov     dword[esp+32], 0        ; success!
3555 Serge 1276
        ret
1277
 
3725 Serge 1278
  .already:
1279
        mov     dword[esp+20], EALREADY
1280
        mov     dword[esp+32], -1
3555 Serge 1281
        ret
1282
 
1283
 
1284
 
1285
 
1286
;-----------------------------------------------------------------
922 mikedld 1287
;
3555 Serge 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:
922 mikedld 1299
 
3589 Serge 1300
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3555 Serge 1301
 
1302
        call    SOCKET_alloc
3725 Serge 1303
        jz      .nomem1
3555 Serge 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
3725 Serge 1315
        jz      .nomem2
1316
        mov     [esp+20], edi   ; application's ebx
922 mikedld 1317
 
3555 Serge 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
 
2434 Serge 1336
        ret
907 mikedld 1337
 
3725 Serge 1338
  .nomem2:
3555 Serge 1339
        mov     eax, ebx
1340
        call    SOCKET_free
3725 Serge 1341
  .nomem1:
1342
        mov     dword[esp+32], -1
1343
        mov     dword[esp+28], ENOMEM
1344
        ret
907 mikedld 1345
 
3555 Serge 1346
 
1347
 
1348
;-----------------------------------------------------------------
261 hidnplayr 1349
;
3555 Serge 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
 
3589 Serge 1362
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3555 Serge 1363
 
1364
        mov     edi, edx
1365
 
1366
        test    ecx, ecx
1367
        jz      .returnall
1368
 
1369
        call    SOCKET_num_to_ptr
3725 Serge 1370
        jz      .invalid
3555 Serge 1371
 
1372
        mov     esi, eax
1373
        mov     ecx, SOCKETBUFFSIZE/4
3725 Serge 1374
        rep movsd
3555 Serge 1375
 
3725 Serge 1376
        mov     dword[esp+32], 0
2434 Serge 1377
        ret
261 hidnplayr 1378
 
3555 Serge 1379
  .returnall:
1380
        mov     ebx, net_sockets
1381
  .next_socket:
1382
        mov     ebx, [ebx + SOCKET.NextPtr]
2434 Serge 1383
        test    ebx, ebx
3555 Serge 1384
        jz      .done
1385
        mov     eax, [ebx + SOCKET.Number]
1386
        stosd
1387
        jmp     .next_socket
1388
  .done:
1389
        xor     eax, eax
1390
        stosd
3725 Serge 1391
        mov     dword[esp+32], eax
1392
        ret
3555 Serge 1393
 
3725 Serge 1394
  .invalid:
1395
        mov     dword[esp+32], -1
1396
        mov     dword[esp+28], EINVAL
2434 Serge 1397
        ret
1154 clevermous 1398
 
3555 Serge 1399
 
1400
;-----------------------------------------------------------------
261 hidnplayr 1401
;
3555 Serge 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:
261 hidnplayr 1414
 
3589 Serge 1415
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
261 hidnplayr 1416
 
3555 Serge 1417
        push    ebx esi ecx
261 hidnplayr 1418
 
3555 Serge 1419
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1420
        je      .udp
261 hidnplayr 1421
 
3555 Serge 1422
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1423
        je      .tcp
1424
 
1425
        pop     ecx esi ebx
2434 Serge 1426
        ret
261 hidnplayr 1427
 
3555 Serge 1428
  .udp:
1429
        mov     bx, [last_UDP_port]
1430
        call    .findit
1431
        mov     [last_UDP_port], bx
1154 clevermous 1432
 
3555 Serge 1433
        pop     ecx esi ebx
2434 Serge 1434
        ret
261 hidnplayr 1435
 
3555 Serge 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
;-----------------------------------------------------------------
261 hidnplayr 1461
;
3555 Serge 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:
261 hidnplayr 1475
 
3589 Serge 1476
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
261 hidnplayr 1477
 
3725 Serge 1478
        pusha
1479
        mov     ecx, socket_mutex
1480
        call    mutex_lock
1481
        popa
1482
 
3555 Serge 1483
        mov     ecx, [eax + SOCKET.Protocol]
1484
        mov     edx, [eax + IP_SOCKET.LocalIP]
1485
        mov     esi, net_sockets
261 hidnplayr 1486
 
907 mikedld 1487
  .next_socket:
3555 Serge 1488
        mov     esi, [esi + SOCKET.NextPtr]
1489
        or      esi, esi
1490
        jz      .port_ok
1491
 
1492
        cmp     [esi + SOCKET.Protocol], ecx
2434 Serge 1493
        jne     .next_socket
3555 Serge 1494
 
1495
        cmp     [esi + IP_SOCKET.LocalIP], edx
2434 Serge 1496
        jne     .next_socket
261 hidnplayr 1497
 
3555 Serge 1498
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1499
        jne     .next_socket
261 hidnplayr 1500
 
3725 Serge 1501
        pusha
1502
        mov     ecx, socket_mutex
1503
        call    mutex_unlock
1504
        popa
1505
 
3589 Serge 1506
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3555 Serge 1507
        ret
261 hidnplayr 1508
 
3555 Serge 1509
  .port_ok:
3725 Serge 1510
        pusha
1511
        mov     ecx, socket_mutex
1512
        call    mutex_unlock
1513
        popa
1514
 
3589 Serge 1515
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3555 Serge 1516
        mov     [eax + UDP_SOCKET.LocalPort], bx
1517
        or      bx, bx                                  ; clear the zero-flag
1518
        ret
261 hidnplayr 1519
 
1520
 
1521
 
3555 Serge 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:
261 hidnplayr 1541
 
3589 Serge 1542
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
261 hidnplayr 1543
 
3555 Serge 1544
        mov     [esp+4], ecx
1545
        push    esi
1546
        mov     esi, esp
261 hidnplayr 1547
 
3555 Serge 1548
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
261 hidnplayr 1549
 
3589 Serge 1550
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3555 Serge 1551
        add     esp, sizeof.socket_queue_entry
261 hidnplayr 1552
 
3555 Serge 1553
        pusha
1554
        lea     ecx, [eax + SOCKET.mutex]
1555
        call    mutex_unlock
1556
        popa
261 hidnplayr 1557
 
3555 Serge 1558
        jmp     SOCKET_notify
261 hidnplayr 1559
 
3555 Serge 1560
  .full:
3589 Serge 1561
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
261 hidnplayr 1562
 
3555 Serge 1563
        pusha
1564
        lea     ecx, [eax + SOCKET.mutex]
1565
        call    mutex_unlock
1566
        popa
261 hidnplayr 1567
 
3555 Serge 1568
        call    kernel_free
1569
        add     esp, 8
261 hidnplayr 1570
 
2434 Serge 1571
        ret
261 hidnplayr 1572
 
1154 clevermous 1573
 
3555 Serge 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
 
3589 Serge 1588
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
3555 Serge 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
 
2434 Serge 1604
        ret
261 hidnplayr 1605
 
3555 Serge 1606
;-----------------------------------------------------------------
261 hidnplayr 1607
;
3555 Serge 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:
261 hidnplayr 1621
 
3589 Serge 1622
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
261 hidnplayr 1623
 
3555 Serge 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
261 hidnplayr 1629
 
3555 Serge 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]
3589 Serge 1638
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3555 Serge 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
3725 Serge 1665
        rep movsd
3555 Serge 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
 
2434 Serge 1675
        ret
261 hidnplayr 1676
 
3555 Serge 1677
;-----------------------------------------------------------------
261 hidnplayr 1678
;
3555 Serge 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:
922 mikedld 1695
 
3589 Serge 1696
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3555 Serge 1697
 
2434 Serge 1698
        pusha
3555 Serge 1699
        lea     ecx, [eax + RING_BUFFER.mutex]
1700
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1701
        popa
261 hidnplayr 1702
 
3555 Serge 1703
        mov     esi, [eax + RING_BUFFER.read_ptr]
1704
        add     esi, edx                                        ; esi = start_ptr + offset
261 hidnplayr 1705
 
3555 Serge 1706
        neg     edx
1707
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1708
        jle     .no_data_at_all
261 hidnplayr 1709
 
3555 Serge 1710
        pusha
1711
        lea     ecx, [eax + RING_BUFFER.mutex]
1712
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1713
        popa
261 hidnplayr 1714
 
3555 Serge 1715
        cmp     ecx, edx
1716
        ja      .less_data
1717
 
1718
  .copy:
3589 Serge 1719
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3555 Serge 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
3725 Serge 1731
        rep movsd
3555 Serge 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
2434 Serge 1740
        popa
261 hidnplayr 1741
 
3589 Serge 1742
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3555 Serge 1743
        xor     ecx, ecx
1744
        ret
261 hidnplayr 1745
 
3555 Serge 1746
  .less_data:
1747
        mov     ecx, edx
1748
        jmp     .copy
261 hidnplayr 1749
 
1750
 
3555 Serge 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:
261 hidnplayr 1765
 
3589 Serge 1766
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3555 Serge 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..
3589 Serge 1791
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3555 Serge 1792
        add     [eax + RING_BUFFER.size], ecx
1793
 
2434 Serge 1794
        push    eax
3555 Serge 1795
        lea     ecx, [eax + RING_BUFFER.mutex]
1796
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1797
        pop     eax
261 hidnplayr 1798
 
2434 Serge 1799
        xor     ecx, ecx
3555 Serge 1800
        ret
261 hidnplayr 1801
 
1802
 
3555 Serge 1803
;-----------------------------------------------------------------
1804
;
1805
; SOCKET_block
1806
;
1807
; Suspends the thread attached to a socket
1808
;
1809
;  IN:  eax = socket ptr
3725 Serge 1810
;  OUT: eax = unchanged
3555 Serge 1811
;
1812
;-----------------------------------------------------------------
1813
align 4
1814
SOCKET_block:
261 hidnplayr 1815
 
3589 Serge 1816
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
261 hidnplayr 1817
 
3555 Serge 1818
        pushf
3725 Serge 1819
        push    eax
3555 Serge 1820
        cli
261 hidnplayr 1821
 
3555 Serge 1822
        ; Set the 'socket is blocked' flag
1823
        or      [eax + SOCKET.state], SS_BLOCKED
261 hidnplayr 1824
 
3555 Serge 1825
        ; Suspend the thread
1826
        push    edx
1827
        mov     edx, [TASK_BASE]
1828
        mov     [edx + TASKDATA.state], 1               ; Suspended
261 hidnplayr 1829
 
3555 Serge 1830
        ; Remember the thread ID so we can wake it up again
1831
        mov     edx, [edx + TASKDATA.pid]
3589 Serge 1832
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3555 Serge 1833
        mov     [eax + SOCKET.TID], edx
1834
        pop     edx
261 hidnplayr 1835
 
3555 Serge 1836
        call    change_task
3725 Serge 1837
        pop     eax
3555 Serge 1838
        popf
261 hidnplayr 1839
 
3589 Serge 1840
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
261 hidnplayr 1841
 
2434 Serge 1842
        ret
261 hidnplayr 1843
 
3555 Serge 1844
 
1845
;-----------------------------------------------------------------
261 hidnplayr 1846
;
3555 Serge 1847
; SOCKET_notify
1848
;
1849
; notify's the owner of a socket that something happened
1850
;
1851
;  IN:  eax = socket ptr
3725 Serge 1852
;  OUT: eax = unchanged
3555 Serge 1853
;
1854
;-----------------------------------------------------------------
1855
align 4
1856
SOCKET_notify:
1857
 
3589 Serge 1858
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3555 Serge 1859
 
1860
        call    SOCKET_check
2434 Serge 1861
        jz      .error
261 hidnplayr 1862
 
3555 Serge 1863
        test    [eax + SOCKET.state], SS_BLOCKED
1864
        jnz     .unblock
261 hidnplayr 1865
 
3725 Serge 1866
;        test    [eax + SOCKET.options], SO_NONBLOCK
1867
;        jz      .error
261 hidnplayr 1868
 
3555 Serge 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
 
3589 Serge 1894
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n"
3555 Serge 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
2434 Serge 1906
        jz      .error
3555 Serge 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:
261 hidnplayr 1919
 
3555 Serge 1920
        ; Run the thread
1921
        mov     [esi + TASKDATA.state], 0       ; Running
3589 Serge 1922
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
261 hidnplayr 1923
 
3555 Serge 1924
  .done:
1925
        pop     esi ecx eax
1926
 
907 mikedld 1927
  .error:
2434 Serge 1928
        ret
261 hidnplayr 1929
 
3555 Serge 1930
 
1931
;--------------------------------------------------------------------
907 mikedld 1932
;
3555 Serge 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
3589 Serge 1951
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
2434 Serge 1952
        or      eax, eax
3555 Serge 1953
        jz      .exit
261 hidnplayr 1954
 
3555 Serge 1955
; zero-initialize allocated memory
1956
        push    eax
1957
        mov     edi, eax
1958
        mov     ecx, SOCKETBUFFSIZE / 4
1959
        xor     eax, eax
3725 Serge 1960
        rep stosd
3555 Serge 1961
        pop     eax
1962
 
1963
; set send-and receive procedures to return -1
3725 Serge 1964
        mov     [eax + SOCKET.snd_proc], .not_yet
1965
        mov     [eax + SOCKET.rcv_proc], .not_yet
3555 Serge 1966
 
3725 Serge 1967
        pusha
1968
        mov     ecx, socket_mutex
1969
        call    mutex_lock
1970
        popa
1971
 
3555 Serge 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
3589 Serge 1992
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3555 Serge 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
2434 Serge 2002
        lea     ecx, [eax + SOCKET.mutex]
3555 Serge 2003
        call    mutex_init
2004
        popa
1019 diamond 2005
 
3555 Serge 2006
; add socket to the list by re-arranging some pointers
2007
        mov     ebx, [net_sockets + SOCKET.NextPtr]
261 hidnplayr 2008
 
3555 Serge 2009
        mov     [eax + SOCKET.PrevPtr], net_sockets
2010
        mov     [eax + SOCKET.NextPtr], ebx
261 hidnplayr 2011
 
3555 Serge 2012
        test    ebx, ebx
2013
        jz      @f
261 hidnplayr 2014
 
3555 Serge 2015
        pusha
2434 Serge 2016
        lea     ecx, [ebx + SOCKET.mutex]
3555 Serge 2017
        call    mutex_lock
2018
        popa
261 hidnplayr 2019
 
3555 Serge 2020
        mov     [ebx + SOCKET.PrevPtr], eax
2021
 
2022
        pusha
2434 Serge 2023
        lea     ecx, [ebx + SOCKET.mutex]
2024
        call    mutex_unlock
3555 Serge 2025
        popa
2026
       @@:
2027
 
2028
        mov     [net_sockets + SOCKET.NextPtr], eax
2029
        or      eax, eax                ; used to clear zero flag
3725 Serge 2030
 
2031
        pusha
2032
        mov     ecx, socket_mutex
2033
        call    mutex_unlock
2034
        popa
2035
 
3555 Serge 2036
  .exit:
2037
        pop     ebx
2038
 
2434 Serge 2039
        ret
261 hidnplayr 2040
 
3725 Serge 2041
  .not_yet:
2042
        mov     dword[esp+20], ENOTCONN
2043
        mov     dword[esp+32], -1
2044
        ret
3555 Serge 2045
 
3725 Serge 2046
 
3555 Serge 2047
;----------------------------------------------------
323 hidnplayr 2048
;
3555 Serge 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
 
3589 Serge 2060
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3555 Serge 2061
 
3725 Serge 2062
        pusha
2063
        mov     ecx, socket_mutex
2064
        call    mutex_lock
2065
        popa
2066
 
3555 Serge 2067
        call    SOCKET_check
2434 Serge 2068
        jz      .error
261 hidnplayr 2069
 
3555 Serge 2070
        push    ebx
1019 diamond 2071
 
3555 Serge 2072
        pusha
2434 Serge 2073
        lea     ecx, [eax + SOCKET.mutex]
2074
        call    mutex_lock
3555 Serge 2075
        popa
2130 serge 2076
 
3555 Serge 2077
        cmp     [eax + SOCKET.Domain], AF_INET4
2078
        jnz     .no_tcp
323 hidnplayr 2079
 
3555 Serge 2080
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2081
        jnz     .no_tcp
323 hidnplayr 2082
 
2434 Serge 2083
        mov     ebx, eax
3555 Serge 2084
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
2085
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
2434 Serge 2086
        mov     eax, ebx
3555 Serge 2087
  .no_tcp:
323 hidnplayr 2088
 
3725 Serge 2089
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3555 Serge 2090
        push    eax                             ; this will be passed to kernel_free
2091
        mov     ebx, [eax + SOCKET.NextPtr]
2092
        mov     eax, [eax + SOCKET.PrevPtr]
2093
 
3589 Serge 2094
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3555 Serge 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
 
3589 Serge 2109
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
3555 Serge 2110
 
907 mikedld 2111
  .error:
3725 Serge 2112
 
2113
        pusha
2114
        mov     ecx, socket_mutex
2115
        call    mutex_unlock
2116
        popa
2117
 
2434 Serge 2118
        ret
323 hidnplayr 2119
 
3555 Serge 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
 
3589 Serge 2133
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3555 Serge 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
3725 Serge 2156
        rep movsd
3555 Serge 2157
 
2158
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2159
 
2434 Serge 2160
        ret
323 hidnplayr 2161
 
3555 Serge 2162
  .fail2:
2163
        add     esp, 4+4+4
2164
  .fail:
3589 Serge 2165
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3555 Serge 2166
        xor     eax, eax
2167
        ret
323 hidnplayr 2168
 
3555 Serge 2169
 
2170
;---------------------------------------------------
261 hidnplayr 2171
;
3555 Serge 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
 
3589 Serge 2184
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3555 Serge 2185
 
3725 Serge 2186
        pusha
2187
        mov     ecx, socket_mutex
2188
        call    mutex_lock
2189
        popa
2190
 
3555 Serge 2191
        mov     eax, net_sockets
2192
 
2193
  .next_socket:
2194
        mov     eax, [eax + SOCKET.NextPtr]
2434 Serge 2195
        or      eax, eax
2196
        jz      .error
3555 Serge 2197
        cmp     [eax + SOCKET.Number], ecx
2198
        jne     .next_socket
261 hidnplayr 2199
 
3555 Serge 2200
        test    eax, eax
261 hidnplayr 2201
 
3725 Serge 2202
        pusha
2203
        mov     ecx, socket_mutex
2204
        call    mutex_unlock
2205
        popa
2206
 
3589 Serge 2207
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3555 Serge 2208
        ret
261 hidnplayr 2209
 
3555 Serge 2210
  .error:
3725 Serge 2211
        pusha
2212
        mov     ecx, socket_mutex
2213
        call    mutex_unlock
2214
        popa
2215
 
2216
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax
3555 Serge 2217
        ret
261 hidnplayr 2218
 
2219
 
3555 Serge 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:
261 hidnplayr 2233
 
3589 Serge 2234
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
261 hidnplayr 2235
 
3555 Serge 2236
        call    SOCKET_check
2237
        jz      .error
261 hidnplayr 2238
 
3555 Serge 2239
        mov     eax, [eax + SOCKET.Number]
261 hidnplayr 2240
 
3589 Serge 2241
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3555 Serge 2242
        ret
261 hidnplayr 2243
 
3555 Serge 2244
  .error:
3589 Serge 2245
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3555 Serge 2246
        ret
261 hidnplayr 2247
 
2248
 
3555 Serge 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:
261 hidnplayr 2262
 
3589 Serge 2263
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
261 hidnplayr 2264
 
3555 Serge 2265
        push    ebx
2266
        mov     ebx, net_sockets
261 hidnplayr 2267
 
3555 Serge 2268
  .next_socket:
2269
        mov     ebx, [ebx + SOCKET.NextPtr]
2270
        or      ebx, ebx
2271
        jz      .done
2272
        cmp     ebx, eax
2273
        jnz     .next_socket
261 hidnplayr 2274
 
3555 Serge 2275
  .done:
2276
        mov     eax, ebx
2277
        test    eax, eax
2278
        pop     ebx
261 hidnplayr 2279
 
3555 Serge 2280
        ret
261 hidnplayr 2281
 
2282
 
2283
 
3555 Serge 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:
261 hidnplayr 2296
 
3589 Serge 2297
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
261 hidnplayr 2298
 
3555 Serge 2299
        push    ebx
2300
        mov     ebx, [TASK_BASE]
2301
        mov     ebx, [ebx + TASKDATA.pid]
2302
        cmp     [eax + SOCKET.PID], ebx
3725 Serge 2303
        pop     ebx
261 hidnplayr 2304
 
3555 Serge 2305
        ret
261 hidnplayr 2306
 
2307
 
2308
 
2309
 
3555 Serge 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:
261 hidnplayr 2324
 
3725 Serge 2325
        pushf
2326
        cli     ; FIXME
2327
 
3589 Serge 2328
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
261 hidnplayr 2329
 
3725 Serge 2330
        pusha
2331
        mov     ecx, socket_mutex
2332
        call    mutex_lock
2333
        popa
2334
 
3555 Serge 2335
        push    ebx
2336
        mov     ebx, net_sockets
261 hidnplayr 2337
 
3555 Serge 2338
  .next_socket:
2339
        mov     ebx, [ebx + SOCKET.NextPtr]
2340
  .next_socket_test:
2341
        test    ebx, ebx
2342
        jz      .done
261 hidnplayr 2343
 
3555 Serge 2344
        cmp     [ebx + SOCKET.PID], edx
2345
        jne     .next_socket
261 hidnplayr 2346
 
3589 Serge 2347
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
261 hidnplayr 2348
 
3555 Serge 2349
        mov     [ebx + SOCKET.PID], 0
2350
        mov     eax, ebx
2351
        mov     ebx, [ebx + SOCKET.NextPtr]
3725 Serge 2352
 
3555 Serge 2353
        pusha
3725 Serge 2354
        mov     ecx, socket_mutex
2355
        call    mutex_unlock
3555 Serge 2356
        popa
3725 Serge 2357
 
2358
        pusha
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:
2372
        popa
2373
 
2374
        pusha
2375
        mov     ecx, socket_mutex
2376
        call    mutex_lock
2377
        popa
2378
 
3555 Serge 2379
        jmp     .next_socket_test
2380
 
2381
  .done:
2382
        pop     ebx
2383
 
3725 Serge 2384
        pusha
2385
        mov     ecx, socket_mutex
2386
        call    mutex_unlock
2387
        popa
2388
 
2389
        popf
2390
 
2434 Serge 2391
        ret
261 hidnplayr 2392
 
3555 Serge 2393
 
2394
 
2395
 
2396
;-----------------------------------------------------------------
261 hidnplayr 2397
;
3555 Serge 2398
; SOCKET_is_connecting
2399
;
2400
;  IN:  eax = socket ptr
2401
;  OUT: /
2402
;
2403
;-----------------------------------------------------------------
261 hidnplayr 2404
 
3555 Serge 2405
align 4
2406
SOCKET_is_connecting:
261 hidnplayr 2407
 
3589 Serge 2408
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
261 hidnplayr 2409
 
3555 Serge 2410
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2411
        or      [eax + SOCKET.options], SS_ISCONNECTING
261 hidnplayr 2412
 
3555 Serge 2413
        jmp     SOCKET_notify
261 hidnplayr 2414
 
2415
 
2416
 
3555 Serge 2417
;-----------------------------------------------------------------
2418
;
2419
; SOCKET_is_connected
2420
;
2421
;  IN:  eax = socket ptr
2422
;  OUT: /
2423
;
2424
;-----------------------------------------------------------------
261 hidnplayr 2425
 
3555 Serge 2426
align 4
2427
SOCKET_is_connected:
261 hidnplayr 2428
 
3589 Serge 2429
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
261 hidnplayr 2430
 
3725 Serge 2431
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2432
        or      [eax + SOCKET.state], SS_ISCONNECTED
261 hidnplayr 2433
 
3555 Serge 2434
        jmp     SOCKET_notify
261 hidnplayr 2435
 
2436
 
2437
 
2438
 
3555 Serge 2439
;-----------------------------------------------------------------
2440
;
2441
; SOCKET_is_disconnecting
2442
;
2443
;  IN:  eax = socket ptr
2444
;  OUT: /
2445
;
2446
;-----------------------------------------------------------------
261 hidnplayr 2447
 
3555 Serge 2448
align 4
2449
SOCKET_is_disconnecting:
261 hidnplayr 2450
 
3589 Serge 2451
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
261 hidnplayr 2452
 
3725 Serge 2453
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2454
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
261 hidnplayr 2455
 
3555 Serge 2456
        jmp     SOCKET_notify
261 hidnplayr 2457
 
2458
 
2459
 
3555 Serge 2460
;-----------------------------------------------------------------
2461
;
2462
; SOCKET_is_disconnected
2463
;
2464
;  IN:  eax = socket ptr
2465
;  OUT: /
2466
;
2467
;-----------------------------------------------------------------
261 hidnplayr 2468
 
3555 Serge 2469
align 4
2470
SOCKET_is_disconnected:
261 hidnplayr 2471
 
3589 Serge 2472
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
261 hidnplayr 2473
 
3725 Serge 2474
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2475
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
261 hidnplayr 2476
 
3555 Serge 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
 
3589 Serge 2505
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3555 Serge 2506
 
3725 Serge 2507
        or      [eax + SOCKET.state], SS_CANTRCVMORE
3555 Serge 2508
 
3589 Serge 2509
        call    SOCKET_notify
2510
 
2434 Serge 2511
        ret
261 hidnplayr 2512
 
3555 Serge 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
 
3589 Serge 2527
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3555 Serge 2528
 
3725 Serge 2529
        or      [eax + SOCKET.state], SS_CANTSENDMORE
2530
        mov     [eax + SOCKET.snd_proc], .notconn
3555 Serge 2531
 
3589 Serge 2532
        call    SOCKET_notify
2533
 
3725 Serge 2534
        ret
2535
 
2536
  .notconn:
2537
        mov     dword[esp+20], ENOTCONN
2538
        mov     dword[esp+32], -1
3555 Serge 2539
        ret