Subversion Repositories Kolibri OS

Rev

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

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