Subversion Repositories Kolibri OS

Rev

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