isnecure send/receive now works... next, secure
[pengine.git] / lib / interComms.php
1 <?php
2 define("NETCOM_PORT", 14001);
3 define("NETCOM_PORT_SSL", 14002);
4
5
6 // comms on this thing are very serial, the server are only capable of processing
7 // one thing at a time... for now
8
9 // the encryption we use here yes, it will be pub/priv but not ssl per se.
10 // how encryption works:
11 // initiate connection:
12 // server -> PEN:b64enc(pubkey):INE
13 // client -> PEN:ACK:INE
14 // client -> PEN:encrypt(pubkey, session key):INE
15 // server -> PEN:ACK:INE
16 // client -> PEN:encrypt(data, session key):INE <-- data transmission starts here
17 // server -> PEN:ACK:INE
18
19 class netCom {
20         
21         function __construct($am_i_a_server = false, $server_addr = "127.0.0.1", $secure = false)
22         {
23                 global $storeLocation;
24                 
25                 // i have to set it to something, right?
26                 $this->semKey = ftok(__FILE__, "p");
27                 $this->encrypt = $secure;
28                 
29                 $this->amserver = $am_i_a_server;
30                 $this->server = $server_addr;
31                 
32                 $this->secure_server = $secure;
33                 
34                 // this bit needs to be a bit more modular
35                 if($this->amserver && $this->secure_server) if(is_file("$storeLocation/mykey.priv")) {
36                         echo "loading key\n";
37                         $kh = fopen("$storeLocation/mykey.priv", "r");
38                         $kdp = fread($kh, filesize("$storeLocation/mykey.priv"));
39                         
40                         $key = openssl_pkey_get_private($kdp);
41                         $output = "";
42                         $km = openssl_pkey_export($key, $output);
43                         echo "key is $output\n";
44                         $this->key_priv = $output;
45                         
46                         $ar_pubkey = openssl_pkey_get_details($key);
47                         $this->key_pub = $ar_pubkey["key"];
48                         
49                         
50                 } else {
51                         echo "generateing key\n";
52                         $key = openssl_pkey_new();
53                         echo "key generated $key\n";
54                         $output = "";
55                         $km = openssl_pkey_export($key, $output);
56                         echo "key is $output\n";
57                         $ar_pubkey = openssl_pkey_get_details($key);
58                         $pubkey = $ar_pubkey["key"];
59                         echo "array is $pubkey\n";
60                         // now lets write some shit
61                         $priv_f = fopen("$storeLocation/mykey.priv", "w");
62                         fwrite($priv_f, $output);
63                         $this->key_priv = $output;
64                         fclose($priv_f);
65                         
66                         $pub_f = fopen("$storeLocation/mykey.pub", "w");
67                         fwrite($pub_f, $pubkey);
68                         $this->key_pub = $pubkey;
69                         fclose($pub_f);
70                         
71                         
72                 }
73         }
74         
75         // initiates a bind if its a server, a connect if its a client
76         function go($callback = "")
77         {
78                 if($this->amserver) {
79                         echo "i am a server, bind!\n";
80                         // here we fork our server
81                         $pid = pcntl_fork();
82                         if($pid == -1) {
83                                 return false;
84                                 // fork failure
85                         } else if ($pid) {
86                                 return true;
87                                 // parent
88                         } else {
89                                 // child
90                                 if($this->secure_server) {
91                                         $this->startSecureServerListener($callback);
92                                 } else {
93                                         $this->startServerListener($callback);
94                                 }
95                         }
96                 } else {
97                         echo "I am a client, connect!\n";
98                         if($this->secure_server) {
99                                 $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
100                                 $res = socket_connect($this->socket, $this->server, NETCOM_PORT_SSL);
101                         } else {
102                                 $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
103                                 $res = socket_connect($this->socket, $this->server, NETCOM_PORT);
104                                 
105                         }
106                 }
107         }
108         
109         function startSecureServerListener($callback)
110         {
111                 $this->listen_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
112                 socket_bind($this->listen_socket, $this->server, NETCOM_PORT_SSL);
113                 socket_listen($this->listen_socket);
114                 
115                 while(true) {
116                         $newsock = socket_accept($this->listen_socket);
117                         echo "Have a new conneciton\n";
118                         // i now have a connection
119                         $pid = pcntl_fork();
120                         if($pid == -1) return false;
121                         else if (!$pid) {
122                                 secureConnection($callback, $newsock);  
123                         }
124                 }               
125         }
126         
127         function secureConnection($callback, $socket)
128         {
129                 // when the secure conneciton starts, we send out pub key
130                 sendMessageInternal($this->key_pub, $socket);
131                 
132                 // then we get a session key
133                 $sesskey_enc = receiveMessageInternal($socket);
134                 
135                 // which we decrypt using our priv key and store.
136                 $this->session_key = openssl_private_decypt();
137                 
138                 // now we go into a message loop.
139         }
140         
141         function startServerListener($callback)
142         {
143                 $this->listen_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
144                 socket_bind($this->listen_socket, $this->server, NETCOM_PORT);
145                 socket_listen($this->listen_socket);
146                 
147                 while(true) {
148                         $newsock = socket_accept($this->listen_socket);
149                         echo "Have a new conneciton\n";
150                         // i now have a connection
151                         $pid = pcntl_fork();
152                         if($pid == -1) return false;
153                         else if (!$pid) {
154                                 $this->insecureConnection($callback, $newsock); 
155                         }
156                 }               
157         }
158         
159         function insecureConnection($callback, $socket)
160         {
161                 $continue = true;
162                 while($continue) {
163                         // wait for a message
164                         $msg_s = $this->receiveMessageInternal($socket);
165                         if(!$msg_s) {
166                                 echo "Connection handler dieing 1\n";
167                                 return false;
168                         }
169                         $msg = unserialize($msg_s);
170                         $retmsg = $callback($msg);
171                         $retval = $this->sendMessageInternal(serialize($retmsg), $socket);
172                         if(!$retval) {
173                                 echo "Connection handler dieing 2\n";
174                                 return false;
175                         }
176                 }
177         }
178         
179         function sendMessage($data)
180         {
181                 $continue = true;
182
183                 $returned = false;
184                 if($this->secure_server) {
185                         $returned = $this->sendMessageSecure($data);
186                 } else {
187                         $returned = $this->sendMessageInsecure($data);
188                 }
189                 
190                 return $returned;
191         }
192         
193         function sendMessageInsecure($data)
194         {
195                 $this->sendMessageInternal(serialize($data), $this->socket);
196                 $returned = $this->receiveMessageInternal($this->socket);
197                 
198                 return unserialize($returned);
199         }
200         
201         function sendMessageInternal($message_data, $comsock)
202         {               
203                 echo "begin send message\n";
204                 $datacomp = base64_encode($message_data);
205                 $tosend = "PEN:$datacomp:INE";
206                 
207                 $retval = socket_send($comsock, $tosend, strlen($tosend), 0);
208                 if(!$retval) {
209                         echo "in smi, retval false\n";
210                         return false;
211                 }
212                 echo "end send message $retval\n";
213                 // get up to one meg of data - this is bad... i can feel this function
214                 // hurting alot
215                 // TODO FIX THIS - its garbage code... im not really sure how to handle this really
216                 // we need to read back as AS:data:EOD - i think it now does.. i hope, tho we need
217                 // timeouts now.
218                 // we wait for an ack
219                 $size = socket_recv($comsock, $recv, 1024, 0);
220                 if($recv != "PEN:ACK:INE") {
221                         echo "invalid response?\n$recv\n";
222                 } else {
223                         echo "smi got ack\n";
224                 }
225                 
226                 return true;
227         }
228         
229         function receiveMessageInternal($comsock)
230         {
231                 echo "begin recieve message\n";
232                 $recvd = "";
233                 $continue = true;
234                 while($continue) {
235                         $size = socket_recv($comsock, $recvd_a, 1024, 0);
236                         
237                         if($size === false) {
238                                 echo "recevie in rmi was false\n";
239                                 return false;
240                         }
241                         $recvd .= $recvd_a;
242                         echo "got $recvd_a so far for $size\n";
243                         if($size == 0) return false;
244                         if(preg_match("/.*\:INE$/", $recvd)) {
245                                 // we have a full string... break out
246                                 $continue = false;
247                                 break;
248                         }
249                 }
250                 
251                 
252                 echo "rec msg next\n";
253                 // first check we got something that makes sense
254                 if(preg_match("/^PEN:.*:INE$/", $recvd) < 1) {
255                         socket_close($comsock);
256                         echo "Returned data is not in right format\n";
257                         // we have a problem jim
258                         return false;
259                 }
260                 $msg = "PEN:ACK:INE";
261                 socket_send($comsock, $msg, strlen($msg), 0);
262                 
263                 echo "got a data packet\n";
264                 $xps = explode(":", $recvd);
265                 
266                 $component =  base64_decode($xps[1]);
267
268                 return $component;
269         }
270          
271         
272         
273         private $server;
274         private $encrypt;
275         private $semKey;
276         private $amserver;
277         private $secure_server;
278         private $socket;
279         private $listen_socket;
280         private $key_priv;
281         private $key_pub;
282         private $session_key;
283         
284 }
285
286 /* packets look like
287  * PEN:base64_enoded data:INE
288  * 
289  * 
290  */
291
292 ?>