Subversion Repositories Kolibri OS

Rev

Rev 9976 | Details | Compare with Previous | Last modification | View Log | RSS feed

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