Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
6916 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2017. 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: 6916 $
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
3601 hidnplayr 603
        push    [IP_LIST + 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
 
3704 hidnplayr 923
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
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
 
5364 hidnplayr 939
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
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:
4219 hidnplayr 956
        mov     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.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
 
1231
        mov     edx, [NET_DRV_LIST + 4*edx]
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:
3556 hidnplayr 1564
        DEBUGF  DEBUG_NETWORK_VERBOSE, "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
  @@:
5155 hidnplayr 1660
 
3545 hidnplayr 1661
        mov     [eax + RING_BUFFER.write_ptr], edi
1662
        pop     edi
1663
 
1664
; update size
1665
        add     [eax + RING_BUFFER.size], ecx
1666
 
1667
; copy the data
1668
        push    ecx
1669
        shr     ecx, 1
1670
        jnc     .nb
1671
        movsb
1672
  .nb:
1673
        shr     ecx, 1
1674
        jnc     .nw
1675
        movsw
1676
  .nw:
1677
        test    ecx, ecx
1678
        jz      .nd
3711 clevermous 1679
        rep movsd
3545 hidnplayr 1680
  .nd:
1681
        pop     ecx
1682
 
1683
; unlock mutex
4344 hidnplayr 1684
        pusha
3545 hidnplayr 1685
        lea     ecx, [eax + RING_BUFFER.mutex]
1686
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
4344 hidnplayr 1687
        popa
3545 hidnplayr 1688
 
1689
        ret
1690
 
5976 hidnplayr 1691
;-----------------------------------------------------------------;
1692
;                                                                 ;
6011 hidnplayr 1693
; socket_ring_read: Read from ring buffer                         ;
5976 hidnplayr 1694
;                                                                 ;
1695
;   IN: eax = ring struct ptr                                     ;
1696
;       ecx = bytes to read                                       ;
1697
;       edx = offset                                              ;
1698
;       edi = ptr to buffer start                                 ;
1699
;                                                                 ;
1700
;  OUT: eax = unchanged                                           ;
1701
;       ecx = number of bytes read (0 on error)                   ;
1702
;       edx = destroyed                                           ;
1703
;       esi = destroyed                                           ;
1704
;       edi = ptr to buffer end                                   ;
1705
;                                                                 ;
1706
;-----------------------------------------------------------------;
3545 hidnplayr 1707
align 4
6011 hidnplayr 1708
socket_ring_read:
3545 hidnplayr 1709
 
3556 hidnplayr 1710
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1711
 
1712
        pusha
1713
        lea     ecx, [eax + RING_BUFFER.mutex]
1714
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1715
        popa
1716
 
1717
        mov     esi, [eax + RING_BUFFER.read_ptr]
1718
        add     esi, edx                                        ; esi = start_ptr + offset
1719
 
1720
        neg     edx
1721
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1722
        jle     .no_data_at_all
1723
 
1724
        pusha
1725
        lea     ecx, [eax + RING_BUFFER.mutex]
1726
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1727
        popa
1728
 
1729
        cmp     ecx, edx
1730
        ja      .less_data
1731
 
1732
  .copy:
3556 hidnplayr 1733
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1734
        push    ecx
1735
        shr     ecx, 1
1736
        jnc     .nb
1737
        movsb
1738
  .nb:
1739
        shr     ecx, 1
1740
        jnc     .nw
1741
        movsw
1742
  .nw:
1743
        test    ecx, ecx
1744
        jz      .nd
3711 clevermous 1745
        rep movsd
3545 hidnplayr 1746
  .nd:
1747
        pop     ecx
1748
        ret
1749
 
1750
  .no_data_at_all:
1751
        pusha
1752
        lea     ecx, [eax + RING_BUFFER.mutex]
1753
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1754
        popa
1755
 
3556 hidnplayr 1756
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1757
        xor     ecx, ecx
1758
        ret
1759
 
1760
  .less_data:
1761
        mov     ecx, edx
1762
        jmp     .copy
1763
 
1764
 
5976 hidnplayr 1765
;-----------------------------------------------------------------;
1766
;                                                                 ;
6011 hidnplayr 1767
; socket_ring_free: Free data from a ringbuffer.                  ;
5976 hidnplayr 1768
;                                                                 ;
1769
;   IN: eax = ptr to ring struct                                  ;
1770
;       ecx = data size                                           ;
1771
;                                                                 ;
1772
;  OUT: ecx = number of freed bytes                               ;
1773
;                                                                 ;
1774
;-----------------------------------------------------------------;
3545 hidnplayr 1775
align 4
6011 hidnplayr 1776
socket_ring_free:
3545 hidnplayr 1777
 
3556 hidnplayr 1778
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 1779
 
1780
        push    eax ecx
1781
        lea     ecx, [eax + RING_BUFFER.mutex]
1782
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1783
        pop     ecx eax
1784
 
1785
        sub     [eax + RING_BUFFER.size], ecx
1786
        jb      .error
1787
        add     [eax + RING_BUFFER.read_ptr], ecx
1788
 
1789
        mov     edx, [eax + RING_BUFFER.end_ptr]
1790
        cmp     [eax + RING_BUFFER.read_ptr], edx
1791
        jb      @f
6413 hidnplayr 1792
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_BUFFER_SIZE
3545 hidnplayr 1793
       @@:
1794
 
1795
        push    eax ecx
1796
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1797
        call    mutex_unlock
1798
        pop     ecx eax
1799
 
1800
        ret
1801
 
1802
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
3556 hidnplayr 1803
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1804
        add     [eax + RING_BUFFER.size], ecx
1805
 
1806
        push    eax
1807
        lea     ecx, [eax + RING_BUFFER.mutex]
1808
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1809
        pop     eax
1810
 
1811
        xor     ecx, ecx
1812
        ret
1813
 
1814
 
5976 hidnplayr 1815
;-----------------------------------------------------------------;
1816
;                                                                 ;
6011 hidnplayr 1817
; socket_block: Suspend the thread attached to a socket.          ;
5976 hidnplayr 1818
;                                                                 ;
1819
;   IN: eax = socket ptr                                          ;
1820
;                                                                 ;
1821
;  OUT: eax = unchanged                                           ;
1822
;                                                                 ;
1823
;-----------------------------------------------------------------;
3545 hidnplayr 1824
align 4
6011 hidnplayr 1825
socket_block:
3545 hidnplayr 1826
 
6908 ashmew2 1827
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1828
 
4520 hidnplayr 1829
        push    eax
1830
 
3545 hidnplayr 1831
        pushf
1832
        cli
1833
 
1834
        ; Set the 'socket is blocked' flag
1835
        or      [eax + SOCKET.state], SS_BLOCKED
1836
 
1837
        ; Suspend the thread
1838
        push    edx
1839
        mov     edx, [TASK_BASE]
1840
        mov     [edx + TASKDATA.state], 1               ; Suspended
1841
 
1842
        ; Remember the thread ID so we can wake it up again
1843
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1844
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1845
        mov     [eax + SOCKET.TID], edx
1846
        pop     edx
4520 hidnplayr 1847
        popf
3545 hidnplayr 1848
 
1849
        call    change_task
3674 hidnplayr 1850
        pop     eax
3545 hidnplayr 1851
 
6908 ashmew2 1852
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continuing\n"
3545 hidnplayr 1853
 
1854
        ret
1855
 
1856
 
5976 hidnplayr 1857
;-----------------------------------------------------------------;
1858
;                                                                 ;
6011 hidnplayr 1859
; socket_notify: Wake up socket owner thread.                     ;
5976 hidnplayr 1860
;                                                                 ;
1861
;   IN: eax = socket ptr                                          ;
1862
;                                                                 ;
1863
;  OUT: eax = unchanged                                           ;
1864
;                                                                 ;
1865
;-----------------------------------------------------------------;
3545 hidnplayr 1866
align 4
6011 hidnplayr 1867
socket_notify:
3545 hidnplayr 1868
 
3556 hidnplayr 1869
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1870
 
6011 hidnplayr 1871
        call    socket_check
3545 hidnplayr 1872
        jz      .error
1873
 
4527 hidnplayr 1874
; Find the associated thread's TASK_DATA
1875
        push    ebx ecx esi
1876
        mov     ebx, [eax + SOCKET.TID]
1877
        test    ebx, ebx
1878
        jz      .error2
1879
        xor     ecx, ecx
3545 hidnplayr 1880
        inc     ecx
4527 hidnplayr 1881
        mov     esi, TASK_DATA
1882
  .next:
1883
        cmp     [esi + TASKDATA.pid], ebx
1884
        je      .found
1885
        inc     ecx
3545 hidnplayr 1886
        add     esi, 0x20
1887
        cmp     ecx, [TASK_COUNT]
4527 hidnplayr 1888
        jbe     .next
1889
 
1890
  .error2:
3545 hidnplayr 1891
; PID not found, TODO: close socket!
4527 hidnplayr 1892
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: error finding thread 0x%x !\n", ebx
1893
        pop     esi ecx ebx
1894
        ret
3545 hidnplayr 1895
 
4527 hidnplayr 1896
  .error:
4528 hidnplayr 1897
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: invalid socket ptr: 0x%x !\n", eax
4527 hidnplayr 1898
        ret
1899
 
1900
  .found:
1901
        test    [eax + SOCKET.state], SS_BLOCKED
4528 hidnplayr 1902
        jnz     .un_block
4527 hidnplayr 1903
 
5976 hidnplayr 1904
; Socket and thread exists and socket is of non blocking type.
4527 hidnplayr 1905
; We'll try to flag an event to the thread.
3545 hidnplayr 1906
        shl     ecx, 8
6908 ashmew2 1907
        or      [SLOT_BASE + ecx + APPDATA.event_mask], EVENT_NETWORK
3545 hidnplayr 1908
 
6413 hidnplayr 1909
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", ebx
4527 hidnplayr 1910
        pop     esi ecx ebx
1911
        ret
3545 hidnplayr 1912
 
4527 hidnplayr 1913
 
4528 hidnplayr 1914
  .un_block:
5976 hidnplayr 1915
; Socket and thread exists and socket is of blocking type
4527 hidnplayr 1916
; We'll try to unblock it.
1917
        and     [eax + SOCKET.state], not SS_BLOCKED    ; Clear the 'socket is blocked' flag
1918
        mov     [esi + TASKDATA.state], 0               ; Run the thread
3545 hidnplayr 1919
 
6908 ashmew2 1920
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
4527 hidnplayr 1921
        pop     esi ecx ebx
3545 hidnplayr 1922
        ret
1923
 
1924
 
5976 hidnplayr 1925
;-----------------------------------------------------------------;
1926
;                                                                 ;
6011 hidnplayr 1927
; socket_alloc: Allocate memory for socket and put new socket     ;
1928
; into the list. Newly created socket is initialized with calling ;
1929
; PID and given a socket number.                                  ;
5976 hidnplayr 1930
;                                                                 ;
1931
;  IN:  /                                                         ;
1932
;                                                                 ;
1933
; OUT:  eax = socket ptr on success                               ;
1934
;       eax = 0 on error                                          ;
1935
;       edi = socket number on success                            ;
1936
;                                                                 ;
1937
;-----------------------------------------------------------------;
3545 hidnplayr 1938
align 4
6011 hidnplayr 1939
socket_alloc:
3545 hidnplayr 1940
 
1941
        push    ebx
1942
 
6413 hidnplayr 1943
        stdcall kernel_alloc, SOCKET_STRUCT_SIZE
5969 hidnplayr 1944
        or      eax, eax
1945
        jz      .nomem
3556 hidnplayr 1946
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1947
 
1948
; zero-initialize allocated memory
1949
        push    eax
1950
        mov     edi, eax
6413 hidnplayr 1951
        mov     ecx, SOCKET_STRUCT_SIZE / 4
3545 hidnplayr 1952
        xor     eax, eax
3711 clevermous 1953
        rep stosd
3545 hidnplayr 1954
        pop     eax
1955
 
1956
; set send-and receive procedures to return -1
3658 hidnplayr 1957
        mov     [eax + SOCKET.snd_proc], .not_yet
1958
        mov     [eax + SOCKET.rcv_proc], .not_yet
3545 hidnplayr 1959
 
3647 hidnplayr 1960
        pusha
1961
        mov     ecx, socket_mutex
1962
        call    mutex_lock
1963
        popa
1964
 
3545 hidnplayr 1965
; find first free socket number and use it
1966
        mov     edi, [last_socket_num]
1967
  .next_socket_number:
1968
        inc     edi
1969
        jz      .next_socket_number     ; avoid socket nr 0
1970
        cmp     edi, -1
1971
        je      .next_socket_number     ; avoid socket nr -1
1972
        mov     ebx, net_sockets
1973
  .next_socket:
1974
        mov     ebx, [ebx + SOCKET.NextPtr]
1975
        test    ebx, ebx
1976
        jz      .last_socket
1977
 
1978
        cmp     [ebx + SOCKET.Number], edi
1979
        jne     .next_socket
1980
        jmp     .next_socket_number
1981
 
1982
  .last_socket:
1983
        mov     [last_socket_num], edi
1984
        mov     [eax + SOCKET.Number], edi
3556 hidnplayr 1985
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 1986
 
1987
; Fill in PID
1988
        mov     ebx, [TASK_BASE]
1989
        mov     ebx, [ebx + TASKDATA.pid]
1990
        mov     [eax + SOCKET.PID], ebx
1991
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1992
 
1993
; init mutex
1994
        pusha
1995
        lea     ecx, [eax + SOCKET.mutex]
1996
        call    mutex_init
1997
        popa
1998
 
1999
; add socket to the list by re-arranging some pointers
2000
        mov     ebx, [net_sockets + SOCKET.NextPtr]
2001
 
2002
        mov     [eax + SOCKET.PrevPtr], net_sockets
2003
        mov     [eax + SOCKET.NextPtr], ebx
2004
 
2005
        test    ebx, ebx
2006
        jz      @f
2007
 
2008
        pusha
2009
        lea     ecx, [ebx + SOCKET.mutex]
2010
        call    mutex_lock
2011
        popa
2012
 
2013
        mov     [ebx + SOCKET.PrevPtr], eax
2014
 
2015
        pusha
2016
        lea     ecx, [ebx + SOCKET.mutex]
2017
        call    mutex_unlock
2018
        popa
2019
       @@:
2020
 
2021
        mov     [net_sockets + SOCKET.NextPtr], eax
3647 hidnplayr 2022
 
2023
        pusha
2024
        mov     ecx, socket_mutex
2025
        call    mutex_unlock
2026
        popa
3545 hidnplayr 2027
        pop     ebx
2028
 
2029
        ret
2030
 
5969 hidnplayr 2031
  .nomem:
2032
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_alloc: Out of memory!\n"
2033
        pop     ebx
2034
        ret
2035
 
3658 hidnplayr 2036
  .not_yet:
3673 hidnplayr 2037
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2038
        mov     dword[esp+32], -1
2039
        ret
3545 hidnplayr 2040
 
3658 hidnplayr 2041
 
5976 hidnplayr 2042
;-----------------------------------------------------------------;
2043
;                                                                 ;
6011 hidnplayr 2044
; socket_free: Free socket data memory and remove socket from     ;
2045
; the list. Caller should lock and unlock socket_mutex.           ;
5976 hidnplayr 2046
;                                                                 ;
2047
;  IN:  eax = socket ptr                                          ;
2048
;                                                                 ;
2049
; OUT:  /                                                         ;
2050
;                                                                 ;
2051
;-----------------------------------------------------------------;
3545 hidnplayr 2052
align 4
6011 hidnplayr 2053
socket_free:
3545 hidnplayr 2054
 
3556 hidnplayr 2055
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 2056
 
6011 hidnplayr 2057
        call    socket_check
3545 hidnplayr 2058
        jz      .error
2059
 
2060
        push    ebx
2061
 
2062
        pusha
2063
        lea     ecx, [eax + SOCKET.mutex]
2064
        call    mutex_lock
2065
        popa
2066
 
5969 hidnplayr 2067
        cmp     [eax + SOCKET.Type], SOCK_STREAM
2068
        jne     .no_stream
3545 hidnplayr 2069
 
2070
        mov     ebx, eax
5969 hidnplayr 2071
        cmp     [eax + STREAM_SOCKET.rcv.start_ptr], 0
2072
        je      @f
2073
        stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
2074
  @@:
2075
        cmp     [ebx + STREAM_SOCKET.snd.start_ptr], 0
2076
        je      @f
2077
        stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
2078
  @@:
3545 hidnplayr 2079
        mov     eax, ebx
5969 hidnplayr 2080
  .no_stream:
3545 hidnplayr 2081
 
3652 hidnplayr 2082
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 2083
        push    eax                             ; this will be passed to kernel_free
2084
        mov     ebx, [eax + SOCKET.NextPtr]
2085
        mov     eax, [eax + SOCKET.PrevPtr]
2086
 
3556 hidnplayr 2087
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 2088
 
2089
        test    eax, eax
2090
        jz      @f
2091
        mov     [eax + SOCKET.NextPtr], ebx
2092
       @@:
2093
 
2094
        test    ebx, ebx
2095
        jz      @f
2096
        mov     [ebx + SOCKET.PrevPtr], eax
2097
       @@:
2098
 
2099
        call    kernel_free
2100
        pop     ebx
2101
 
3652 hidnplayr 2102
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
2103
 
2104
  .error:
3545 hidnplayr 2105
        ret
2106
 
5969 hidnplayr 2107
  .error1:
2108
        pop     ebx
5976 hidnplayr 2109
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_free: error!\n"
5969 hidnplayr 2110
        DEBUGF  DEBUG_NETWORK_ERROR, "socket ptr=0x%x caller=0x%x\n", eax, [esp]
2111
        ret
2112
 
5976 hidnplayr 2113
;-----------------------------------------------------------------;
2114
;                                                                 ;
6011 hidnplayr 2115
; socket_fork: Create a child socket.                             ;
5976 hidnplayr 2116
;                                                                 ;
2117
;  IN:  ebx = socket number                                       ;
2118
;                                                                 ;
2119
; OUT:  eax = child socket number on success                      ;
2120
;       eax = 0 on error                                          ;
2121
;                                                                 ;
2122
;-----------------------------------------------------------------;
3545 hidnplayr 2123
align 4
6011 hidnplayr 2124
socket_fork:
3545 hidnplayr 2125
 
3556 hidnplayr 2126
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 2127
 
2128
; Exit if backlog queue is full
2129
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
2130
        cmp     ax, [ebx + SOCKET.backlog]
2131
        jae     .fail
2132
 
2133
; Allocate new socket
2134
        push    ebx
6011 hidnplayr 2135
        call    socket_alloc
3545 hidnplayr 2136
        pop     ebx
4535 hidnplayr 2137
        test    eax, eax
3545 hidnplayr 2138
        jz      .fail
2139
 
2140
        push    eax
2141
        mov     esi, esp
2142
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
2143
        pop     eax
2144
 
2145
; Copy structure from current socket to new
3817 hidnplayr 2146
; We start at PID to preserve the socket num, 2 pointers and mutex
2147
; TID will be filled in later
3545 hidnplayr 2148
        lea     esi, [ebx + SOCKET.PID]
2149
        lea     edi, [eax + SOCKET.PID]
2150
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
3711 clevermous 2151
        rep movsd
3545 hidnplayr 2152
 
2153
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2154
 
3817 hidnplayr 2155
; Notify owner of parent socket
2156
        push    eax
2157
        mov     eax, ebx
6011 hidnplayr 2158
        call    socket_notify
3817 hidnplayr 2159
        pop     eax
2160
 
3545 hidnplayr 2161
        ret
2162
 
2163
  .fail2:
2164
        add     esp, 4+4+4
2165
  .fail:
3556 hidnplayr 2166
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 2167
        xor     eax, eax
2168
        ret
2169
 
2170
 
5976 hidnplayr 2171
;-----------------------------------------------------------------;
2172
;                                                                 ;
6011 hidnplayr 2173
; socket_num_to_ptr: Get socket structure address by its number.  ;
5976 hidnplayr 2174
;                                                                 ;
2175
;  IN:  ecx = socket number                                       ;
2176
;                                                                 ;
2177
; OUT:  eax = socket ptr                                          ;
2178
;       eax = 0 on error                                          ;
2179
;                                                                 ;
2180
;-----------------------------------------------------------------;
3545 hidnplayr 2181
align 4
6011 hidnplayr 2182
socket_num_to_ptr:
3545 hidnplayr 2183
 
3556 hidnplayr 2184
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2185
 
3647 hidnplayr 2186
        pusha
2187
        mov     ecx, socket_mutex
2188
        call    mutex_lock
2189
        popa
2190
 
3545 hidnplayr 2191
        mov     eax, net_sockets
2192
  .next_socket:
2193
        mov     eax, [eax + SOCKET.NextPtr]
5969 hidnplayr 2194
        test    eax, eax
3545 hidnplayr 2195
        jz      .error
2196
        cmp     [eax + SOCKET.Number], ecx
2197
        jne     .next_socket
2198
 
3647 hidnplayr 2199
        pusha
2200
        mov     ecx, socket_mutex
2201
        call    mutex_unlock
2202
        popa
2203
 
3556 hidnplayr 2204
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2205
        ret
2206
 
2207
  .error:
3647 hidnplayr 2208
        pusha
2209
        mov     ecx, socket_mutex
2210
        call    mutex_unlock
2211
        popa
2212
 
4574 hidnplayr 2213
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: socket %u not found!\n", eax
2214
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: caller = 0x%x\n", [esp]
3545 hidnplayr 2215
        ret
2216
 
2217
 
5976 hidnplayr 2218
;-----------------------------------------------------------------;
2219
;                                                                 ;
6011 hidnplayr 2220
; socket_ptr_to_num: Get socket number by its address.            ;
5976 hidnplayr 2221
;                                                                 ;
2222
;  IN:  eax = socket ptr                                          ;
2223
;                                                                 ;
2224
; OUT:  eax = socket number                                       ;
2225
;       eax = 0 on error                                          ;
2226
;       ZF = set on error                                         ;
2227
;                                                                 ;
2228
;-----------------------------------------------------------------;
3545 hidnplayr 2229
align 4
6011 hidnplayr 2230
socket_ptr_to_num:
3545 hidnplayr 2231
 
3556 hidnplayr 2232
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2233
 
6011 hidnplayr 2234
        call    socket_check
3545 hidnplayr 2235
        jz      .error
2236
 
2237
        mov     eax, [eax + SOCKET.Number]
2238
 
3556 hidnplayr 2239
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2240
        ret
2241
 
2242
  .error:
3556 hidnplayr 2243
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2244
        ret
2245
 
2246
 
5976 hidnplayr 2247
;-----------------------------------------------------------------;
2248
;                                                                 ;
6011 hidnplayr 2249
; socket_check: Checks if the given ptr is really a socket ptr.   ;
5976 hidnplayr 2250
;                                                                 ;
2251
;  IN:  eax = socket ptr                                          ;
2252
;                                                                 ;
2253
; OUT:  eax = 0 on error                                          ;
2254
;       ZF = set on error                                         ;
2255
;                                                                 ;
2256
;-----------------------------------------------------------------;
3545 hidnplayr 2257
align 4
6011 hidnplayr 2258
socket_check:
3545 hidnplayr 2259
 
3556 hidnplayr 2260
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2261
 
5969 hidnplayr 2262
        test    eax, eax
2263
        jz      .error
3545 hidnplayr 2264
        push    ebx
2265
        mov     ebx, net_sockets
2266
 
2267
  .next_socket:
2268
        mov     ebx, [ebx + SOCKET.NextPtr]
2269
        or      ebx, ebx
2270
        jz      .done
2271
        cmp     ebx, eax
2272
        jnz     .next_socket
2273
 
2274
  .done:
2275
        mov     eax, ebx
2276
        test    eax, eax
2277
        pop     ebx
5969 hidnplayr 2278
        ret
3545 hidnplayr 2279
 
5969 hidnplayr 2280
  .error:
5976 hidnplayr 2281
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_check: called with argument 0\n"
5969 hidnplayr 2282
        DEBUGF  DEBUG_NETWORK_ERROR, "stack: 0x%x, 0x%x, 0x%x\n", [esp], [esp+4], [esp+8]
3545 hidnplayr 2283
        ret
2284
 
2285
 
2286
 
5976 hidnplayr 2287
;-----------------------------------------------------------------;
2288
;                                                                 ;
6011 hidnplayr 2289
; socket_check_owner: Check if the caller app owns the socket.    ;
5976 hidnplayr 2290
;                                                                 ;
2291
;  IN:  eax = socket ptr                                          ;
2292
;                                                                 ;
2293
; OUT:  ZF = true/false                                           ;
2294
;                                                                 ;
2295
;-----------------------------------------------------------------;
3545 hidnplayr 2296
align 4
6011 hidnplayr 2297
socket_check_owner:
3545 hidnplayr 2298
 
3556 hidnplayr 2299
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2300
 
2301
        push    ebx
2302
        mov     ebx, [TASK_BASE]
2303
        mov     ebx, [ebx + TASKDATA.pid]
2304
        cmp     [eax + SOCKET.PID], ebx
3711 clevermous 2305
        pop     ebx
3545 hidnplayr 2306
 
2307
        ret
2308
 
2309
 
2310
 
2311
 
5976 hidnplayr 2312
;-----------------------------------------------------------------;
2313
;                                                                 ;
6011 hidnplayr 2314
; socket_process_end: Kernel calls this function when a certain   ;
2315
; process ends. This function will check if the process had any   ;
2316
; open sockets and update them accordingly (clean up).            ;
5976 hidnplayr 2317
;                                                                 ;
2318
;  IN:  edx = pid                                                 ;
2319
;                                                                 ;
2320
; OUT:  /                                                         ;
2321
;                                                                 ;
2322
;-----------------------------------------------------------------;
3545 hidnplayr 2323
align 4
6011 hidnplayr 2324
socket_process_end:
3545 hidnplayr 2325
 
4436 hidnplayr 2326
        ret     ; FIXME
2327
 
4056 hidnplayr 2328
        cmp     [net_sockets + SOCKET.NextPtr], 0       ; Are there any active sockets at all?
2329
        je      .quickret                               ; nope, exit immediately
2330
 
2331
; TODO: run the following code in another thread, to avoid deadlock
2332
 
3556 hidnplayr 2333
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2334
 
3647 hidnplayr 2335
        pusha
2336
        mov     ecx, socket_mutex
2337
        call    mutex_lock
2338
        popa
2339
 
3545 hidnplayr 2340
        push    ebx
2341
        mov     ebx, net_sockets
2342
 
2343
  .next_socket:
2344
        mov     ebx, [ebx + SOCKET.NextPtr]
2345
  .next_socket_test:
2346
        test    ebx, ebx
2347
        jz      .done
2348
 
2349
        cmp     [ebx + SOCKET.PID], edx
2350
        jne     .next_socket
2351
 
3556 hidnplayr 2352
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2353
 
2354
        mov     [ebx + SOCKET.PID], 0
2355
        mov     eax, ebx
2356
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2357
 
3545 hidnplayr 2358
        pusha
3652 hidnplayr 2359
        cmp     [eax + SOCKET.Domain], AF_INET4
2360
        jne     .free
2361
 
2362
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2363
        jne     .free
2364
 
6011 hidnplayr 2365
        call    tcp_disconnect
3652 hidnplayr 2366
        jmp     .closed
2367
 
2368
  .free:
6011 hidnplayr 2369
        call    socket_free
3652 hidnplayr 2370
 
2371
  .closed:
3545 hidnplayr 2372
        popa
2373
        jmp     .next_socket_test
2374
 
2375
  .done:
2376
        pop     ebx
2377
 
3647 hidnplayr 2378
        pusha
2379
        mov     ecx, socket_mutex
2380
        call    mutex_unlock
2381
        popa
2382
 
4056 hidnplayr 2383
  .quickret:
3545 hidnplayr 2384
        ret
2385
 
2386
 
2387
 
2388
 
5976 hidnplayr 2389
;-----------------------------------------------------------------;
2390
;                                                                 ;
6011 hidnplayr 2391
; socket_is_connecting: Update socket state.                      ;
5976 hidnplayr 2392
;                                                                 ;
2393
;  IN:  eax = socket ptr                                          ;
2394
;                                                                 ;
2395
;  OUT: /                                                         ;
2396
;                                                                 ;
2397
;-----------------------------------------------------------------;
3545 hidnplayr 2398
align 4
6011 hidnplayr 2399
socket_is_connecting:
3545 hidnplayr 2400
 
3556 hidnplayr 2401
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2402
 
4025 hidnplayr 2403
        and     [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2404
        or      [eax + SOCKET.state], SS_ISCONNECTING
2405
        ret
3545 hidnplayr 2406
 
2407
 
2408
 
5976 hidnplayr 2409
;-----------------------------------------------------------------;
2410
;                                                                 ;
6011 hidnplayr 2411
; socket_is_connected: Update socket state.                       ;
5976 hidnplayr 2412
;                                                                 ;
2413
;  IN:  eax = socket ptr                                          ;
2414
;                                                                 ;
2415
;  OUT: /                                                         ;
2416
;                                                                 ;
2417
;-----------------------------------------------------------------;
3545 hidnplayr 2418
align 4
6011 hidnplayr 2419
socket_is_connected:
3545 hidnplayr 2420
 
3556 hidnplayr 2421
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2422
 
3674 hidnplayr 2423
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2424
        or      [eax + SOCKET.state], SS_ISCONNECTED
6011 hidnplayr 2425
        jmp     socket_notify
3545 hidnplayr 2426
 
2427
 
2428
 
2429
 
5976 hidnplayr 2430
;-----------------------------------------------------------------;
2431
;                                                                 ;
6011 hidnplayr 2432
; socket_is_disconnecting: Update socket state.                   ;
5976 hidnplayr 2433
;                                                                 ;
2434
;  IN:  eax = socket ptr                                          ;
2435
;                                                                 ;
2436
;  OUT: /                                                         ;
2437
;                                                                 ;
2438
;-----------------------------------------------------------------;
3545 hidnplayr 2439
align 4
6011 hidnplayr 2440
socket_is_disconnecting:
3545 hidnplayr 2441
 
3556 hidnplayr 2442
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2443
 
3674 hidnplayr 2444
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2445
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
6011 hidnplayr 2446
        jmp     socket_notify
3545 hidnplayr 2447
 
2448
 
2449
 
5976 hidnplayr 2450
;-----------------------------------------------------------------;
2451
;                                                                 ;
6011 hidnplayr 2452
; socket_is_disconnected: Update socket state.                    ;
5976 hidnplayr 2453
;                                                                 ;
2454
;  IN:  eax = socket ptr                                          ;
2455
;                                                                 ;
2456
;  OUT: /                                                         ;
2457
;                                                                 ;
2458
;-----------------------------------------------------------------;
3545 hidnplayr 2459
align 4
6011 hidnplayr 2460
socket_is_disconnected:
3545 hidnplayr 2461
 
3556 hidnplayr 2462
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2463
 
3674 hidnplayr 2464
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2465
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
6011 hidnplayr 2466
        jmp     socket_notify
3545 hidnplayr 2467
 
2468
 
2469
 
5976 hidnplayr 2470
;-----------------------------------------------------------------;
2471
;                                                                 ;
6011 hidnplayr 2472
; socket_cant_recv_more: Update socket state.                     ;
5976 hidnplayr 2473
;                                                                 ;
2474
;  IN:  eax = socket ptr                                          ;
2475
;                                                                 ;
2476
;  OUT: /                                                         ;
2477
;                                                                 ;
2478
;-----------------------------------------------------------------;
3545 hidnplayr 2479
align 4
6011 hidnplayr 2480
socket_cant_recv_more:
3545 hidnplayr 2481
 
3556 hidnplayr 2482
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2483
 
3674 hidnplayr 2484
        or      [eax + SOCKET.state], SS_CANTRCVMORE
6011 hidnplayr 2485
        jmp     socket_notify
3545 hidnplayr 2486
 
3565 hidnplayr 2487
 
3545 hidnplayr 2488
 
5976 hidnplayr 2489
;-----------------------------------------------------------------;
2490
;                                                                 ;
6011 hidnplayr 2491
; socket_cant_send_more: Update socket state.                     ;
5976 hidnplayr 2492
;                                                                 ;
2493
;  IN:  eax = socket ptr                                          ;
2494
;                                                                 ;
2495
;  OUT: /                                                         ;
2496
;                                                                 ;
2497
;-----------------------------------------------------------------;
3545 hidnplayr 2498
align 4
6011 hidnplayr 2499
socket_cant_send_more:
3545 hidnplayr 2500
 
3556 hidnplayr 2501
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2502
 
3674 hidnplayr 2503
        or      [eax + SOCKET.state], SS_CANTSENDMORE
3658 hidnplayr 2504
        mov     [eax + SOCKET.snd_proc], .notconn
6011 hidnplayr 2505
        jmp     socket_notify
3545 hidnplayr 2506
 
3658 hidnplayr 2507
  .notconn:
3673 hidnplayr 2508
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2509
        mov     dword[esp+32], -1
5356 serge 2510
        ret