Subversion Repositories Kolibri OS

Rev

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

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