Subversion Repositories Kolibri OS

Rev

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

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