File: join_port.ml

package info (click to toggle)
jocaml 4.01.0-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 16,736 kB
  • ctags: 23,836
  • sloc: ml: 111,262; ansic: 32,746; sh: 6,057; lisp: 4,230; makefile: 3,861; asm: 3,734; awk: 88; perl: 45; fortran: 21; sed: 19; cs: 9
file content (125 lines) | stat: -rw-r--r-- 3,756 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*            Luc Maranget, projet Moscova, INRIA Rocquencourt         *)
(*                                                                     *)
(*  Copyright 2005 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  under the terms of the Q Public License version 1.0.               *)
(*                                                                     *)
(***********************************************************************)

(* $Id: join_port.ml 10588 2010-06-17 16:37:18Z maranget $ *)

(*DEBUG*)open Join_debug
(*DEBUG*)open Printf
open Join_misc
open Unix

exception Failed of string * exn

type server =
  {
    loc_port : Unix.sockaddr ;
    loc_sock : Unix.file_descr ;
  }


(* Notice when port is zero, then a fresh port is allocated by bind  *)
let create_port porto =
  let sock =
    try
      let port = match porto with
      | None -> ADDR_INET (inet_addr_any, 0)
      | Some p -> p in
      let s =
	socket
	  (Unix.domain_of_sockaddr port)
	  SOCK_STREAM 0 in
      try
	set_close_on_exec s ;
        setsockopt s SO_REUSEADDR true;
	bind s port ;
        listen s 5;
        s
      with e -> close s ; raise e
    with e ->
(*DEBUG*)debug1 "CREATE PORT" "%s" (exn_to_string e) ;
        raise (Failed (exn_to_string e, e)) in
  let sockaddr = 
    let sockaddr = getsockname sock in
    match porto with
    | Some _ -> sockaddr
    | None -> match sockaddr with
      | ADDR_INET (_, port) ->  ADDR_INET (Join_misc.get_local_addr (), port)
      | ADDR_UNIX _ -> assert false in
  {loc_port=sockaddr ;  loc_sock=sock ; }


let rec force_accept s =
  try
(*DEBUG*)debug1 "UNIX" "accept" ;
    let (_,addr) as r = Unix.accept s in
(*DEBUG*)debug1 "UNIX" "accepted: %s" (string_of_sockaddr addr) ;
    r
  with
  | Unix_error((EAGAIN|EINTR),_,_) -> 
(*DEBUG*)debug1 "accept" "%s" "try again" ;
      force_accept s


and listener port when_accepted () =
  try while true do
(*DEBUG*)debug1 "LISTENER"
(*DEBUG*)  "now accept on %s" (string_of_sockaddr port.loc_port) ;
    let s,_ = force_accept port.loc_sock in
(*DEBUG*)debug1 "LISTENER" "%s" "someone coming" ;
    let link = Join_link.create s in
    try when_accepted link
    with e ->
(*DEBUG*)debug1 "LISTENER"
(*DEBUG*)  "acceptor died of %s" (Join_misc.exn_to_string e) ;
      ()
  done with  e ->
(*DEBUG*)debug0 "LISTENER"
(*DEBUG*)  "died of %s" (Join_misc.exn_to_string e) ;
    ()

let establish_server port when_accepted =
  let local_port = create_port port in
  Join_scheduler.create_process (listener local_port when_accepted) ;
  local_port.loc_port, local_port

let kill_server { loc_sock = sock ; } =
(*DEBUG*)debug1 "KILL_SERVER" "" ;
  try
    Unix.shutdown sock Unix.SHUTDOWN_ALL ;
    Unix.close sock ;
  with e ->
(*DEBUG*)debug0 "KILL SERVER"
(*DEBUG*)  "got %s" (Join_misc.exn_to_string e) ;
    raise e
    



let connect sockaddr =
  let sock =
    try
      let sock =
        socket
          (match sockaddr with
          | ADDR_INET (_,_) -> PF_INET
          | ADDR_UNIX _ -> PF_UNIX)
          SOCK_STREAM 0 in
      try
        Unix.connect sock sockaddr ;
(*DEBUG*)debug1 "CONNECTED" "%s" (string_of_sockaddr (getpeername sock)) ;
        sock
      with z -> close sock ; raise z
    with
    | e ->
(*DEBUG*)debug1 "CONNECT" "%s" (exn_to_string e) ;
        raise (Failed (exn_to_string e,e)) in
  Join_link.create sock (* Can fail only for OutOfMemory *)