112 | | }}} |
113 | | |
| 113 | #include <fcntl.h> |
| 114 | #include <stdio.h> |
| 115 | #include <stdlib.h> |
| 116 | #include <sys/time.h> |
| 117 | #include <sys/stat.h> |
| 118 | #include <unistd.h> |
| 119 | #include <string.h> |
| 120 | |
| 121 | #define MAXServerResquest 1024 |
| 122 | |
| 123 | int main() |
| 124 | { |
| 125 | int f2s, s2f; // fifo file descriptors |
| 126 | char *f2sName = "/tmp/f2s_fw"; // filo names |
| 127 | char *s2fName = "/tmp/s2f_fw"; // |
| 128 | char serverRequest[MAXServerResquest]; // buffer for the request |
| 129 | fd_set rfds; // flag for select |
| 130 | struct timeval tv; // timeout |
| 131 | tv.tv_sec = 1; // 1 second |
| 132 | tv.tv_usec = 0; // |
| 133 | |
| 134 | mkfifo(s2fName, 0666); // fifo creation |
| 135 | mkfifo(f2sName, 0666); |
| 136 | |
| 137 | /* open both fifos */ |
| 138 | s2f = open(s2fName, O_RDWR); // fifo openning |
| 139 | f2s = open(f2sName, O_RDWR); |
| 140 | |
| 141 | do { |
| 142 | FD_ZERO(&rfds); // erase all flags |
| 143 | FD_SET(s2f, &rfds); // wait for s2f |
| 144 | |
| 145 | if (select(s2f+1, &rfds, NULL, NULL, &tv) != 0) { // wait until timeout |
| 146 | if (FD_ISSET(s2f, &rfds)) { // something to read |
| 147 | int nbchar; |
| 148 | if ((nbchar = read(s2f, serverRequest, MAXServerResquest)) == 0) break; |
| 149 | serverRequest[nbchar]=0; |
| 150 | fprintf(stderr,"%s", serverRequest); |
| 151 | write(f2s, serverRequest, nbchar); |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | while (1); |
| 156 | |
| 157 | close(f2s); |
| 158 | close(s2f); |
| 159 | |
| 160 | return 0; |
| 161 | } |
| 162 | }}} |
| 163 | |
| 164 | **server.py** |
| 165 | {{{#!python |
| 166 | #!/usr/bin/env python |
| 167 | import os, time |
| 168 | |
| 169 | s2fName = '/tmp/s2f_fw' |
| 170 | if not os.path.exists(s2fName): |
| 171 | os.mkfifo(s2fName) |
| 172 | s2f = open(s2fName,'w+') |
| 173 | |
| 174 | f2sName = '/tmp/f2s_fw' |
| 175 | if not os.path.exists(f2sName): |
| 176 | os.mkfifo(f2sName) |
| 177 | f2s = open(f2sName,'r') |
| 178 | |
| 179 | s2f.write("w hello\n") |
| 180 | s2f.flush() |
| 181 | str = f2s.readline() |
| 182 | print '%s' % str, |
| 183 | |
| 184 | f2s.close() |
| 185 | s2f.close() |
| 186 | }}} |
| 207 | **Pour tester le server http** |
| 208 | - Dans un premier terminal, après l'avoir compiler, lancez le programme fake. Il s'agit du même programme fake.c que précédement, qui reçoit une requête depuis une fifo s2f et qui renvoi une réponse. |
| 209 | {{{ |
| 210 | cd fake |
| 211 | make |
| 212 | ./fake |
| 213 | }}} |
| 214 | - Dans un second terminal, lancez le server.py. C'est un server http en python. |
| 215 | {{{ |
| 216 | cd server/www |
| 217 | ../server.py |
| 218 | }}} |
| 219 | - Sur votre navigateur préféré, visualisez la page index.html à l'adresse 127.0.0.1:8000 |
| 220 | - Vous devez voir apparaitre un logo et une case avec un bouton enter. |
| 221 | - La page `index.html` contient deux "frames": |
| 222 | - Le premier avec le logo. |
| 223 | - Le second est contient la case et le bouton. Le code html de cette case est obtenu par l'exécution du programme Python `cgi-bin/main.py`. |
| 224 | - Notez qu'il n'est pas très utile d'avoir produit cette page par un programme python car la page n'est pas dynamique (son code est toujours le même) mais c'est pour donner la possibilité de la rendre dynamique. |
| 225 | - Lorsque vous écrivez quelque-chose dans la case, la page index.html demande l'exécution de script `cgi-bin/led.py` |
| 226 | - le script `led.py` envoi le contenu de la case sur la fifo `s2f` attendue par `fake` et produit une page presque indentique à main.py avec deux différences. |
| 227 | - Elle affiche ce qui a été reçu de la fifo `f2s` |
| 228 | - Elle est remplacée au bout d'une seconde par la page `main.py` grace à une commande `<META>` |
| 229 | |
| 230 | **server.py** |
| 231 | Le server affiche la page index.htlm du présente dans le répetoire de lanceeltécoute le port 8000, |
| 232 | {{{#!python |
| 233 | #!/usr/bin/env python |
| 234 | import BaseHTTPServer |
| 235 | import CGIHTTPServer |
| 236 | import cgitb; cgitb.enable() |
| 237 | |
| 238 | server = BaseHTTPServer.HTTPServer |
| 239 | handler = CGIHTTPServer.CGIHTTPRequestHandler |
| 240 | server_address = ("", 8000) |
| 241 | handler.cgi_directories = ["/cgi-bin"] |
| 242 | |
| 243 | httpd = server(server_address, handler) |
| 244 | httpd.serve_forever() |
| 245 | }}} |
| 246 | |
| 247 | **index.html** |
| 248 | {{{ |
| 249 | <html> |
| 250 | <head><title>Peri Web Server</title></head> |
| 251 | <frameset rows="100,*" frameborder=0> |
| 252 | <frame src="img/peri.png"> |
| 253 | <frame src="cgi-bin/main.py"> |
| 254 | </frameset> |
| 255 | </html> |
| 256 | }}} |
| 257 | |
| 258 | **main.py** |
| 259 | {{{#!python |
| 260 | #!/usr/bin/env python |
| 261 | |
| 262 | html=""" |
| 263 | <head> |
| 264 | <title>Peri Web Server</title> |
| 265 | </head> |
| 266 | <body> |
| 267 | LEDS:<br/> |
| 268 | <form method="POST" action="led.py"> |
| 269 | <input name="val" cols="20"></input> |
| 270 | <input type="submit" value="Entrer"> |
| 271 | </form> |
| 272 | </body> |
| 273 | """ |
| 274 | |
| 275 | print html |
| 276 | }}} |
| 277 | |
| 278 | **led.py** |
| 279 | {{{#!python |
| 280 | #!/usr/bin/env python |
| 281 | import cgi, os, time,sys |
| 282 | form = cgi.FieldStorage() |
| 283 | val = form.getvalue('val') |
| 284 | |
| 285 | s2fName = '/tmp/s2f_fw' |
| 286 | f2sName = '/tmp/f2s_fw' |
| 287 | s2f = open(s2fName,'w+') |
| 288 | f2s = open(f2sName,'r',0) |
| 289 | |
| 290 | s2f.write("w %s\n" % val) |
| 291 | s2f.flush() |
| 292 | res = f2s.readline() |
| 293 | f2s.close() |
| 294 | s2f.close() |
| 295 | |
| 296 | html=""" |
| 297 | <head> |
| 298 | <title>Peri Web Server</title> |
| 299 | <META HTTP-EQUIV="Refresh" CONTENT="1; URL=/cgi-bin/main.py"> |
| 300 | </head> |
| 301 | <body> |
| 302 | LEDS:<br/> |
| 303 | <form method="POST" action="led.py"> |
| 304 | <input name="val" cols="20"></input> |
| 305 | <input type="submit" value="Entrer"> |
| 306 | set %s |
| 307 | </form> |
| 308 | </body> |
| 309 | """ % (val,) |
| 310 | |
| 311 | print html |
| 312 | }}} |
| 313 | |
| 314 | **Pour l'exécution sur la carte !RaspberryPi** |
| 315 | - Vous devez copier tout `server-fake` sur la carte de votre choix. Vous ne pouvez pas être plus de deux binômes par carte. |
| 316 | - Vous lancez fake et le server http comme précédement. |
| 317 | - Sur votre navigateur, vous devez mettre une exception au proxy pour l'adresse du routeurs des !RaspberryPi `132.227.102.36`. |
| 318 | - Si vous êtes sur la carte **20**, vous mettez comme URL 132.227.102.36:8**020**. Vous faites de manière semblable pour les autres cartes. |
| 319 | - Si vous êtes le second binôme sur la carte *20*, l'URL est 132.227.102.36.8**120**, et dans le script `server.py` vous devez écouter le port **8001**. |
| 320 | - Le routeur des !RaspberryPi a été programmé pour renvoyer les requêtes http reçues sur le port 8xyy avec x=(0 ou 1) et yy=(20,21,...,25) sur le carte yy et le port 800x. |
| 321 | |
| 322 | **Travail demandé** |
| 323 | |
| 324 | - Modifier fake.c et led.py pour commander les leds. |