Subversion Repositories Kolibri OS

Rev

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

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