├── Makefile ├── README ├── amqp-rest.h ├── amqp.conf ├── amqp_conf.c ├── amqp_conf.re.c ├── http_handler.cpp ├── ini_parse.c ├── main.cpp └── tools.c /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ -ggdb -o amqp-rest main.cpp -levent -lrabbitmq -lrabbitmq++ -L/usr/local/lib -I/usr/local/includes -I../librabbitmq++ -L../librabbitmq++/rabbitmq++/build/Release/ -Iamqpcpp 3 | 4 | re2c: 5 | re2c -o amqp_conf.c amqp_conf.re.c 6 | 7 | run: 8 | ./amqp-rest n.conf 9 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | INTRODUCTION 2 | 3 | The amqp-rest is hi-perfomance light (600K) HTTP server based libevent, realise two methods: 4 | 5 | HTTP GET - the reading from queue one item by BASIC.GET AMQP method 6 | HTTP POST - publish to exchange by BASIC.PUBLISH AMQP method 7 | the result from broker return by json. Using in WEB/AJAX technologies. 8 | 9 | curl http://10.0.0.1:8080/sss/q2 // get one item from queue "q2" 10 | {"result": "OK", "message":"message 2", size : 2} 11 | // message is text message, size is queue size. 12 | the name of queue is last part from url, after last slash (q_name): /any/path/and/q_name 13 | 14 | read all messages: the url must have parm "?all" 15 | 16 | curl http://10.0.0.1:8080/sss/q2?all 17 | {"result": "OK", "count" : 2, messages ["message 3","the text\"xxxx\" tttt"]} 18 | // 19 | read queue size: the url must have parm "?count" 20 | 21 | curl http://10.0.0.1:8080/sss/q2?count 22 | {"result": "Ok", "count": 3 } 23 | ATTENTION the count use QUEUE.DECLARE method. If queue not exist - it will created. 24 | 25 | publish to exchange "ex1" by key "news": the exchange name is last part from url, after last slash the routing key is url parm afret "?" 26 | 27 | curl -d 'some post data' http://10.0.0.1:8080/sss/ex1?news 28 | {"result": "Ok"} 29 | the loging is ( log file ) 30 | 31 | 2010/04/12 03:22:32 NOTICE :server started 32 | 2010/04/12 03:22:47 CONTENT: 10.0.0.1 GET /sss/q2 byte:9 200 OK 33 | 2010/04/12 03:26:07 CONTENT: 10.0.0.1 GET /sss/q2?all bytes 79 200 OK 34 | 2010/04/12 03:33:11 CONTENT: 10.0.0.1 POST /sss/ex1?news bytes: 14 200 OK 35 | 36 | INSTALLATION 37 | 38 | You must install the libevent http://monkey.org/~provos/libevent/ 39 | You must install amqpcpp lib http://code.google.com/p/rabbitcpp/ 40 | or http://github.com/akalend/amqpcpp 41 | 42 | run Makefile; 43 | copy amqp-rest to /usr/local/bin 44 | copy n.cont to /usr/local/etc/amqp-rest.conf 45 | 46 | edit the amqp-rest.conf 47 | 48 | logfile /usr/local/var/amqp.log; # logfile 49 | pidfile /tmp/amqp.pid; # pidfile 50 | 51 | log_level notice; # the level of logging : error, notice, warning, debug 52 | daemon on; # daemon mode 53 | 54 | port 80; # http port, default 80 55 | http 10.0.0.1; # bind IP 56 | 57 | amqp :5672; # amqp connection string psw:login@host:port/vhost 58 | ./amqp-rest 59 | default config file path is /usr/local/etc/amqo-rest.conf 60 | 61 | the restart -> send SIGHUP to amqp-rest 62 | the stop is: ./amqp-rest stop (if config in the default path) 63 | 64 | PERFORMANCE 65 | 66 | ab -c 5 -n 1000 http://10.0.0.1:8080/xxx/q2 67 | 68 | concurrency Level: 5 69 | Time taken for tests: 0.745 seconds 70 | Complete requests: 1000 71 | Failed requests: 0 72 | Write errors: 0 73 | Total transferred: 84000 bytes 74 | HTML transferred: 21000 bytes 75 | Requests per second: 1342.95 [#/sec] (mean) 76 | Time per request: 3.723 [ms] (mean) 77 | Time per request: 0.745 [ms] (mean, across all concurrent requests) 78 | Transfer rate: 110.16 [Kbytes/sec] received -------------------------------------------------------------------------------- /amqp-rest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * amqp-rest.h 3 | * amqp-rest 4 | * 5 | * Created by Alexandre Kalendarev on 30.04.10. 6 | * 7 | */ 8 | 9 | #ifndef __AMQPREST__ 10 | #define __AMQPREST__ 11 | 12 | typedef struct { 13 | int fd; 14 | unsigned char *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof, *ptok,parm; 15 | unsigned int line; 16 | } Scanner; 17 | 18 | 19 | enum log_type_e { 20 | LOG_STDERR, 21 | LOG_ERROR, 22 | LOG_CONTENT, 23 | LOG_ALERT, 24 | LOG_WARNING, 25 | LOG_NOTICE, 26 | LOG_DEBUG 27 | }; 28 | 29 | typedef struct { 30 | int log_fd; 31 | int pidfd; 32 | char * confile; 33 | char * amqp_connect; 34 | char * bind; 35 | char * logfile; 36 | char * pidfile; 37 | AMQPQueue * queue; 38 | AMQPExchange * exchange; 39 | short daemon; 40 | short port; 41 | char ip[16]; 42 | char ** ppa; 43 | short log_level; 44 | 45 | } ctx; 46 | 47 | int scan(Scanner *s); 48 | 49 | #endif -------------------------------------------------------------------------------- /amqp.conf: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | config file for amqp-rest 4 | */ 5 | 6 | 7 | #logfile /usr/local/var/amqp.log; # logfile 8 | logfile /Users/akalend/projects/amqp-rest/amqp-rest.log; 9 | 10 | #pidfile /usr/local/var/amqp.pid; # pidfile 11 | pidfile /Users/akalend/projects/amqp-rest/amqp-rest.pid; 12 | 13 | log_level debug; # the level of logging : error, notice, warning, debug 14 | 15 | daemon on; # daemon mode 16 | 17 | port 8080; # http port, default 80 18 | http 10.0.0.1; # bind IP 19 | 20 | amqp :5672; # amqp connection string 21 | 22 | 23 | -------------------------------------------------------------------------------- /amqp_conf.c: -------------------------------------------------------------------------------- 1 | /* Generated by re2c 0.13.3 on Fri May 7 19:03:46 2010 */ 2 | #line 1 "amqp_conf.re.c" 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define EOI 0 12 | 13 | //typedef unsigned int uint; 14 | typedef unsigned char uchar; 15 | 16 | #define BSIZE 8192 17 | 18 | #define YYCTYPE uchar 19 | #define YYCURSOR cursor 20 | #define YYLIMIT s->lim 21 | #define YYMARKER s->ptr 22 | #define YYFILL(n) {cursor = fill(s, cursor);} 23 | 24 | #define RET(i) {s->cur = cursor; return i;} 25 | 26 | #include "amqp-rest.h" 27 | 28 | unsigned char *fill(Scanner *s, uchar *cursor){ 29 | if(!s->eof) { 30 | unsigned int cnt = s->tok - s->bot; 31 | if(cnt){ 32 | memcpy(s->bot, s->tok, s->lim - s->tok); 33 | s->tok = s->bot; 34 | s->ptr -= cnt; 35 | cursor -= cnt; 36 | s->pos -= cnt; 37 | s->lim -= cnt; 38 | } 39 | if((s->top - s->lim) < BSIZE){ 40 | unsigned char *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar)); 41 | memcpy(buf, s->tok, s->lim - s->tok); 42 | s->tok = buf; 43 | s->ptr = &buf[s->ptr - s->bot]; 44 | cursor = &buf[cursor - s->bot]; 45 | s->pos = &buf[s->pos - s->bot]; 46 | s->lim = &buf[s->lim - s->bot]; 47 | s->top = &s->lim[BSIZE]; 48 | free(s->bot); 49 | s->bot = buf; 50 | } 51 | if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){ 52 | s->eof = &s->lim[cnt]; *(s->eof)++ = '\n'; 53 | } 54 | s->lim += cnt; 55 | } 56 | return cursor; 57 | } 58 | 59 | int scan(Scanner *s){ 60 | unsigned char *cursor = s->cur; 61 | int ret=0; 62 | std: 63 | s->tok = cursor; 64 | #line 78 "amqp_conf.re.c" 65 | 66 | 67 | 68 | #line 69 "amqp_conf.c" 69 | { 70 | YYCTYPE yych; 71 | 72 | if ((YYLIMIT - YYCURSOR) < 9) YYFILL(9); 73 | yych = *YYCURSOR; 74 | switch (yych) { 75 | case 0x09: goto yy18; 76 | case 0x0A: goto yy20; 77 | case 0x0B: 78 | case 0x0C: goto yy11; 79 | case 0x0D: goto yy13; 80 | case ' ': goto yy16; 81 | case '#': goto yy4; 82 | case '/': goto yy2; 83 | case ';': goto yy14; 84 | case 'a': goto yy10; 85 | case 'd': goto yy6; 86 | case 'h': goto yy9; 87 | case 'l': goto yy7; 88 | case 'p': goto yy8; 89 | default: goto yy22; 90 | } 91 | yy2: 92 | ++YYCURSOR; 93 | switch ((yych = *YYCURSOR)) { 94 | case '*': goto yy66; 95 | default: goto yy3; 96 | } 97 | yy3: 98 | #line 134 "amqp_conf.re.c" 99 | { 100 | printf("unexpected character: %c line %d \n", *s->tok, s->line); 101 | goto std; 102 | } 103 | #line 104 "amqp_conf.c" 104 | yy4: 105 | ++YYCURSOR; 106 | #line 83 "amqp_conf.re.c" 107 | { goto unixcomment; } 108 | #line 109 "amqp_conf.c" 109 | yy6: 110 | yych = *(YYMARKER = ++YYCURSOR); 111 | switch (yych) { 112 | case 'a': goto yy60; 113 | default: goto yy3; 114 | } 115 | yy7: 116 | yych = *(YYMARKER = ++YYCURSOR); 117 | switch (yych) { 118 | case 'o': goto yy46; 119 | default: goto yy3; 120 | } 121 | yy8: 122 | yych = *(YYMARKER = ++YYCURSOR); 123 | switch (yych) { 124 | case 'i': goto yy35; 125 | case 'o': goto yy36; 126 | default: goto yy3; 127 | } 128 | yy9: 129 | yych = *(YYMARKER = ++YYCURSOR); 130 | switch (yych) { 131 | case 't': goto yy31; 132 | default: goto yy3; 133 | } 134 | yy10: 135 | yych = *(YYMARKER = ++YYCURSOR); 136 | switch (yych) { 137 | case 'm': goto yy26; 138 | default: goto yy3; 139 | } 140 | yy11: 141 | ++YYCURSOR; 142 | yych = *YYCURSOR; 143 | goto yy25; 144 | yy12: 145 | #line 120 "amqp_conf.re.c" 146 | { RET(8912); goto std; } 147 | #line 148 "amqp_conf.c" 148 | yy13: 149 | yych = *++YYCURSOR; 150 | switch (yych) { 151 | case 0x0A: goto yy23; 152 | default: goto yy25; 153 | } 154 | yy14: 155 | ++YYCURSOR; 156 | #line 122 "amqp_conf.re.c" 157 | { goto std; } 158 | #line 159 "amqp_conf.c" 159 | yy16: 160 | ++YYCURSOR; 161 | #line 123 "amqp_conf.re.c" 162 | { goto std; } 163 | #line 164 "amqp_conf.c" 164 | yy18: 165 | ++YYCURSOR; 166 | #line 124 "amqp_conf.re.c" 167 | { goto std; } 168 | #line 169 "amqp_conf.c" 169 | yy20: 170 | ++YYCURSOR; 171 | yy21: 172 | #line 127 "amqp_conf.re.c" 173 | { 174 | if(cursor == s->eof) RET(EOI); 175 | s->pos = cursor; s->line++; 176 | goto std; 177 | } 178 | #line 179 "amqp_conf.c" 179 | yy22: 180 | yych = *++YYCURSOR; 181 | goto yy3; 182 | yy23: 183 | yych = *++YYCURSOR; 184 | goto yy21; 185 | yy24: 186 | ++YYCURSOR; 187 | if (YYLIMIT == YYCURSOR) YYFILL(1); 188 | yych = *YYCURSOR; 189 | yy25: 190 | switch (yych) { 191 | case 0x0B: 192 | case 0x0C: 193 | case 0x0D: goto yy24; 194 | default: goto yy12; 195 | } 196 | yy26: 197 | yych = *++YYCURSOR; 198 | switch (yych) { 199 | case 'q': goto yy28; 200 | default: goto yy27; 201 | } 202 | yy27: 203 | YYCURSOR = YYMARKER; 204 | goto yy3; 205 | yy28: 206 | yych = *++YYCURSOR; 207 | switch (yych) { 208 | case 'p': goto yy29; 209 | default: goto yy27; 210 | } 211 | yy29: 212 | ++YYCURSOR; 213 | #line 108 "amqp_conf.re.c" 214 | { 215 | s->parm = 4; 216 | goto param; 217 | } 218 | #line 219 "amqp_conf.c" 219 | yy31: 220 | yych = *++YYCURSOR; 221 | switch (yych) { 222 | case 't': goto yy32; 223 | default: goto yy27; 224 | } 225 | yy32: 226 | yych = *++YYCURSOR; 227 | switch (yych) { 228 | case 'p': goto yy33; 229 | default: goto yy27; 230 | } 231 | yy33: 232 | ++YYCURSOR; 233 | #line 104 "amqp_conf.re.c" 234 | { 235 | s->parm = 6; 236 | goto ip_param; 237 | } 238 | #line 239 "amqp_conf.c" 239 | yy35: 240 | yych = *++YYCURSOR; 241 | switch (yych) { 242 | case 'd': goto yy40; 243 | default: goto yy27; 244 | } 245 | yy36: 246 | yych = *++YYCURSOR; 247 | switch (yych) { 248 | case 'r': goto yy37; 249 | default: goto yy27; 250 | } 251 | yy37: 252 | yych = *++YYCURSOR; 253 | switch (yych) { 254 | case 't': goto yy38; 255 | default: goto yy27; 256 | } 257 | yy38: 258 | ++YYCURSOR; 259 | #line 99 "amqp_conf.re.c" 260 | { 261 | s->parm = 3; 262 | goto dparam; 263 | } 264 | #line 265 "amqp_conf.c" 265 | yy40: 266 | yych = *++YYCURSOR; 267 | switch (yych) { 268 | case 'f': goto yy41; 269 | default: goto yy27; 270 | } 271 | yy41: 272 | yych = *++YYCURSOR; 273 | switch (yych) { 274 | case 'i': goto yy42; 275 | default: goto yy27; 276 | } 277 | yy42: 278 | yych = *++YYCURSOR; 279 | switch (yych) { 280 | case 'l': goto yy43; 281 | default: goto yy27; 282 | } 283 | yy43: 284 | yych = *++YYCURSOR; 285 | switch (yych) { 286 | case 'e': goto yy44; 287 | default: goto yy27; 288 | } 289 | yy44: 290 | ++YYCURSOR; 291 | #line 113 "amqp_conf.re.c" 292 | { 293 | s->parm = 7; 294 | goto param; 295 | } 296 | #line 297 "amqp_conf.c" 297 | yy46: 298 | yych = *++YYCURSOR; 299 | switch (yych) { 300 | case 'g': goto yy47; 301 | default: goto yy27; 302 | } 303 | yy47: 304 | yych = *++YYCURSOR; 305 | switch (yych) { 306 | case '_': goto yy48; 307 | case 'f': goto yy49; 308 | default: goto yy27; 309 | } 310 | yy48: 311 | yych = *++YYCURSOR; 312 | switch (yych) { 313 | case 'l': goto yy54; 314 | default: goto yy27; 315 | } 316 | yy49: 317 | yych = *++YYCURSOR; 318 | switch (yych) { 319 | case 'i': goto yy50; 320 | default: goto yy27; 321 | } 322 | yy50: 323 | yych = *++YYCURSOR; 324 | switch (yych) { 325 | case 'l': goto yy51; 326 | default: goto yy27; 327 | } 328 | yy51: 329 | yych = *++YYCURSOR; 330 | switch (yych) { 331 | case 'e': goto yy52; 332 | default: goto yy27; 333 | } 334 | yy52: 335 | ++YYCURSOR; 336 | #line 90 "amqp_conf.re.c" 337 | { 338 | s->parm = 2; 339 | goto param; 340 | } 341 | #line 342 "amqp_conf.c" 342 | yy54: 343 | yych = *++YYCURSOR; 344 | switch (yych) { 345 | case 'e': goto yy55; 346 | default: goto yy27; 347 | } 348 | yy55: 349 | yych = *++YYCURSOR; 350 | switch (yych) { 351 | case 'v': goto yy56; 352 | default: goto yy27; 353 | } 354 | yy56: 355 | yych = *++YYCURSOR; 356 | switch (yych) { 357 | case 'e': goto yy57; 358 | default: goto yy27; 359 | } 360 | yy57: 361 | yych = *++YYCURSOR; 362 | switch (yych) { 363 | case 'l': goto yy58; 364 | default: goto yy27; 365 | } 366 | yy58: 367 | ++YYCURSOR; 368 | #line 95 "amqp_conf.re.c" 369 | { 370 | s->parm = 5; 371 | goto lparam; 372 | } 373 | #line 374 "amqp_conf.c" 374 | yy60: 375 | yych = *++YYCURSOR; 376 | switch (yych) { 377 | case 'e': goto yy61; 378 | default: goto yy27; 379 | } 380 | yy61: 381 | yych = *++YYCURSOR; 382 | switch (yych) { 383 | case 'm': goto yy62; 384 | default: goto yy27; 385 | } 386 | yy62: 387 | yych = *++YYCURSOR; 388 | switch (yych) { 389 | case 'o': goto yy63; 390 | default: goto yy27; 391 | } 392 | yy63: 393 | yych = *++YYCURSOR; 394 | switch (yych) { 395 | case 'n': goto yy64; 396 | default: goto yy27; 397 | } 398 | yy64: 399 | ++YYCURSOR; 400 | #line 85 "amqp_conf.re.c" 401 | { 402 | s->parm = 1; 403 | goto _bool; 404 | } 405 | #line 406 "amqp_conf.c" 406 | yy66: 407 | ++YYCURSOR; 408 | #line 82 "amqp_conf.re.c" 409 | { goto comment; } 410 | #line 411 "amqp_conf.c" 411 | } 412 | #line 138 "amqp_conf.re.c" 413 | 414 | //s->tok = cursor; s->parm =3; goto param; 415 | //(PATH)*";" { RET(2001); } 416 | // 417 | 418 | 419 | 420 | param: 421 | s->ptok=cursor; 422 | 423 | #line 424 "amqp_conf.c" 424 | { 425 | YYCTYPE yych; 426 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); 427 | yych = *YYCURSOR; 428 | switch (yych) { 429 | case '-': goto yy70; 430 | case '.': 431 | case '/': goto yy72; 432 | case '0': 433 | case '1': 434 | case '2': 435 | case '3': 436 | case '4': 437 | case '5': 438 | case '6': 439 | case '7': 440 | case '8': 441 | case '9': 442 | case 'A': 443 | case 'B': 444 | case 'C': 445 | case 'D': 446 | case 'E': 447 | case 'F': 448 | case 'G': 449 | case 'H': 450 | case 'I': 451 | case 'J': 452 | case 'K': 453 | case 'L': 454 | case 'M': 455 | case 'N': 456 | case 'O': 457 | case 'P': 458 | case 'Q': 459 | case 'R': 460 | case 'S': 461 | case 'T': 462 | case 'U': 463 | case 'V': 464 | case 'W': 465 | case 'X': 466 | case 'Y': 467 | case 'Z': 468 | case '_': 469 | case 'a': 470 | case 'b': 471 | case 'c': 472 | case 'd': 473 | case 'e': 474 | case 'f': 475 | case 'g': 476 | case 'h': 477 | case 'i': 478 | case 'j': 479 | case 'k': 480 | case 'l': 481 | case 'm': 482 | case 'n': 483 | case 'o': 484 | case 'p': 485 | case 'q': 486 | case 'r': 487 | case 's': 488 | case 't': 489 | case 'u': 490 | case 'v': 491 | case 'w': 492 | case 'x': 493 | case 'y': 494 | case 'z': goto yy73; 495 | case ':': 496 | case '@': goto yy76; 497 | case ';': goto yy74; 498 | default: goto yy77; 499 | } 500 | yy70: 501 | yych = *(YYMARKER = ++YYCURSOR); 502 | switch (yych) { 503 | case '-': 504 | case '.': 505 | case '/': 506 | case '0': 507 | case '1': 508 | case '2': 509 | case '3': 510 | case '4': 511 | case '5': 512 | case '6': 513 | case '7': 514 | case '8': 515 | case '9': 516 | case 'A': 517 | case 'B': 518 | case 'C': 519 | case 'D': 520 | case 'E': 521 | case 'F': 522 | case 'G': 523 | case 'H': 524 | case 'I': 525 | case 'J': 526 | case 'K': 527 | case 'L': 528 | case 'M': 529 | case 'N': 530 | case 'O': 531 | case 'P': 532 | case 'Q': 533 | case 'R': 534 | case 'S': 535 | case 'T': 536 | case 'U': 537 | case 'V': 538 | case 'W': 539 | case 'X': 540 | case 'Y': 541 | case 'Z': 542 | case '_': 543 | case 'a': 544 | case 'b': 545 | case 'c': 546 | case 'd': 547 | case 'e': 548 | case 'f': 549 | case 'g': 550 | case 'h': 551 | case 'i': 552 | case 'j': 553 | case 'k': 554 | case 'l': 555 | case 'm': 556 | case 'n': 557 | case 'o': 558 | case 'p': 559 | case 'q': 560 | case 'r': 561 | case 's': 562 | case 't': 563 | case 'u': 564 | case 'v': 565 | case 'w': 566 | case 'x': 567 | case 'y': 568 | case 'z': goto yy88; 569 | case ';': goto yy90; 570 | default: goto yy71; 571 | } 572 | yy71: 573 | #line 153 "amqp_conf.re.c" 574 | { goto param; } 575 | #line 576 "amqp_conf.c" 576 | yy72: 577 | yych = *(YYMARKER = ++YYCURSOR); 578 | switch (yych) { 579 | case '-': goto yy88; 580 | case '.': 581 | case '/': 582 | case '0': 583 | case '1': 584 | case '2': 585 | case '3': 586 | case '4': 587 | case '5': 588 | case '6': 589 | case '7': 590 | case '8': 591 | case '9': 592 | case 'A': 593 | case 'B': 594 | case 'C': 595 | case 'D': 596 | case 'E': 597 | case 'F': 598 | case 'G': 599 | case 'H': 600 | case 'I': 601 | case 'J': 602 | case 'K': 603 | case 'L': 604 | case 'M': 605 | case 'N': 606 | case 'O': 607 | case 'P': 608 | case 'Q': 609 | case 'R': 610 | case 'S': 611 | case 'T': 612 | case 'U': 613 | case 'V': 614 | case 'W': 615 | case 'X': 616 | case 'Y': 617 | case 'Z': 618 | case '_': 619 | case 'a': 620 | case 'b': 621 | case 'c': 622 | case 'd': 623 | case 'e': 624 | case 'f': 625 | case 'g': 626 | case 'h': 627 | case 'i': 628 | case 'j': 629 | case 'k': 630 | case 'l': 631 | case 'm': 632 | case 'n': 633 | case 'o': 634 | case 'p': 635 | case 'q': 636 | case 'r': 637 | case 's': 638 | case 't': 639 | case 'u': 640 | case 'v': 641 | case 'w': 642 | case 'x': 643 | case 'y': 644 | case 'z': goto yy86; 645 | case ':': 646 | case '@': goto yy80; 647 | case ';': goto yy91; 648 | default: goto yy71; 649 | } 650 | yy73: 651 | yych = *(YYMARKER = ++YYCURSOR); 652 | switch (yych) { 653 | case '-': goto yy88; 654 | case '.': 655 | case '/': goto yy86; 656 | case '0': 657 | case '1': 658 | case '2': 659 | case '3': 660 | case '4': 661 | case '5': 662 | case '6': 663 | case '7': 664 | case '8': 665 | case '9': 666 | case 'A': 667 | case 'B': 668 | case 'C': 669 | case 'D': 670 | case 'E': 671 | case 'F': 672 | case 'G': 673 | case 'H': 674 | case 'I': 675 | case 'J': 676 | case 'K': 677 | case 'L': 678 | case 'M': 679 | case 'N': 680 | case 'O': 681 | case 'P': 682 | case 'Q': 683 | case 'R': 684 | case 'S': 685 | case 'T': 686 | case 'U': 687 | case 'V': 688 | case 'W': 689 | case 'X': 690 | case 'Y': 691 | case 'Z': 692 | case '_': 693 | case 'a': 694 | case 'b': 695 | case 'c': 696 | case 'd': 697 | case 'e': 698 | case 'f': 699 | case 'g': 700 | case 'h': 701 | case 'i': 702 | case 'j': 703 | case 'k': 704 | case 'l': 705 | case 'm': 706 | case 'n': 707 | case 'o': 708 | case 'p': 709 | case 'q': 710 | case 'r': 711 | case 's': 712 | case 't': 713 | case 'u': 714 | case 'v': 715 | case 'w': 716 | case 'x': 717 | case 'y': 718 | case 'z': goto yy84; 719 | case ':': 720 | case '@': goto yy80; 721 | case ';': goto yy83; 722 | default: goto yy71; 723 | } 724 | yy74: 725 | ++YYCURSOR; 726 | yy75: 727 | #line 149 "amqp_conf.re.c" 728 | { RET(303); } 729 | #line 730 "amqp_conf.c" 730 | yy76: 731 | yych = *(YYMARKER = ++YYCURSOR); 732 | switch (yych) { 733 | case '.': 734 | case '/': 735 | case '0': 736 | case '1': 737 | case '2': 738 | case '3': 739 | case '4': 740 | case '5': 741 | case '6': 742 | case '7': 743 | case '8': 744 | case '9': 745 | case ':': 746 | case ';': 747 | case '@': 748 | case 'A': 749 | case 'B': 750 | case 'C': 751 | case 'D': 752 | case 'E': 753 | case 'F': 754 | case 'G': 755 | case 'H': 756 | case 'I': 757 | case 'J': 758 | case 'K': 759 | case 'L': 760 | case 'M': 761 | case 'N': 762 | case 'O': 763 | case 'P': 764 | case 'Q': 765 | case 'R': 766 | case 'S': 767 | case 'T': 768 | case 'U': 769 | case 'V': 770 | case 'W': 771 | case 'X': 772 | case 'Y': 773 | case 'Z': 774 | case '_': 775 | case 'a': 776 | case 'b': 777 | case 'c': 778 | case 'd': 779 | case 'e': 780 | case 'f': 781 | case 'g': 782 | case 'h': 783 | case 'i': 784 | case 'j': 785 | case 'k': 786 | case 'l': 787 | case 'm': 788 | case 'n': 789 | case 'o': 790 | case 'p': 791 | case 'q': 792 | case 'r': 793 | case 's': 794 | case 't': 795 | case 'u': 796 | case 'v': 797 | case 'w': 798 | case 'x': 799 | case 'y': 800 | case 'z': goto yy81; 801 | default: goto yy71; 802 | } 803 | yy77: 804 | yych = *++YYCURSOR; 805 | goto yy71; 806 | yy78: 807 | ++YYCURSOR; 808 | #line 150 "amqp_conf.re.c" 809 | { RET(301 ); } 810 | #line 811 "amqp_conf.c" 811 | yy80: 812 | ++YYCURSOR; 813 | if (YYLIMIT == YYCURSOR) YYFILL(1); 814 | yych = *YYCURSOR; 815 | yy81: 816 | switch (yych) { 817 | case '.': 818 | case '/': 819 | case '0': 820 | case '1': 821 | case '2': 822 | case '3': 823 | case '4': 824 | case '5': 825 | case '6': 826 | case '7': 827 | case '8': 828 | case '9': 829 | case ':': 830 | case '@': 831 | case 'A': 832 | case 'B': 833 | case 'C': 834 | case 'D': 835 | case 'E': 836 | case 'F': 837 | case 'G': 838 | case 'H': 839 | case 'I': 840 | case 'J': 841 | case 'K': 842 | case 'L': 843 | case 'M': 844 | case 'N': 845 | case 'O': 846 | case 'P': 847 | case 'Q': 848 | case 'R': 849 | case 'S': 850 | case 'T': 851 | case 'U': 852 | case 'V': 853 | case 'W': 854 | case 'X': 855 | case 'Y': 856 | case 'Z': 857 | case '_': 858 | case 'a': 859 | case 'b': 860 | case 'c': 861 | case 'd': 862 | case 'e': 863 | case 'f': 864 | case 'g': 865 | case 'h': 866 | case 'i': 867 | case 'j': 868 | case 'k': 869 | case 'l': 870 | case 'm': 871 | case 'n': 872 | case 'o': 873 | case 'p': 874 | case 'q': 875 | case 'r': 876 | case 's': 877 | case 't': 878 | case 'u': 879 | case 'v': 880 | case 'w': 881 | case 'x': 882 | case 'y': 883 | case 'z': goto yy80; 884 | case ';': goto yy78; 885 | default: goto yy82; 886 | } 887 | yy82: 888 | YYCURSOR = YYMARKER; 889 | goto yy71; 890 | yy83: 891 | yych = *++YYCURSOR; 892 | goto yy75; 893 | yy84: 894 | ++YYCURSOR; 895 | if (YYLIMIT == YYCURSOR) YYFILL(1); 896 | yych = *YYCURSOR; 897 | switch (yych) { 898 | case '-': goto yy88; 899 | case '.': 900 | case '/': goto yy86; 901 | case '0': 902 | case '1': 903 | case '2': 904 | case '3': 905 | case '4': 906 | case '5': 907 | case '6': 908 | case '7': 909 | case '8': 910 | case '9': 911 | case 'A': 912 | case 'B': 913 | case 'C': 914 | case 'D': 915 | case 'E': 916 | case 'F': 917 | case 'G': 918 | case 'H': 919 | case 'I': 920 | case 'J': 921 | case 'K': 922 | case 'L': 923 | case 'M': 924 | case 'N': 925 | case 'O': 926 | case 'P': 927 | case 'Q': 928 | case 'R': 929 | case 'S': 930 | case 'T': 931 | case 'U': 932 | case 'V': 933 | case 'W': 934 | case 'X': 935 | case 'Y': 936 | case 'Z': 937 | case '_': 938 | case 'a': 939 | case 'b': 940 | case 'c': 941 | case 'd': 942 | case 'e': 943 | case 'f': 944 | case 'g': 945 | case 'h': 946 | case 'i': 947 | case 'j': 948 | case 'k': 949 | case 'l': 950 | case 'm': 951 | case 'n': 952 | case 'o': 953 | case 'p': 954 | case 'q': 955 | case 'r': 956 | case 's': 957 | case 't': 958 | case 'u': 959 | case 'v': 960 | case 'w': 961 | case 'x': 962 | case 'y': 963 | case 'z': goto yy84; 964 | case ':': 965 | case '@': goto yy80; 966 | case ';': goto yy83; 967 | default: goto yy82; 968 | } 969 | yy86: 970 | ++YYCURSOR; 971 | if (YYLIMIT == YYCURSOR) YYFILL(1); 972 | yych = *YYCURSOR; 973 | switch (yych) { 974 | case '-': goto yy88; 975 | case '.': 976 | case '/': 977 | case '0': 978 | case '1': 979 | case '2': 980 | case '3': 981 | case '4': 982 | case '5': 983 | case '6': 984 | case '7': 985 | case '8': 986 | case '9': 987 | case 'A': 988 | case 'B': 989 | case 'C': 990 | case 'D': 991 | case 'E': 992 | case 'F': 993 | case 'G': 994 | case 'H': 995 | case 'I': 996 | case 'J': 997 | case 'K': 998 | case 'L': 999 | case 'M': 1000 | case 'N': 1001 | case 'O': 1002 | case 'P': 1003 | case 'Q': 1004 | case 'R': 1005 | case 'S': 1006 | case 'T': 1007 | case 'U': 1008 | case 'V': 1009 | case 'W': 1010 | case 'X': 1011 | case 'Y': 1012 | case 'Z': 1013 | case '_': 1014 | case 'a': 1015 | case 'b': 1016 | case 'c': 1017 | case 'd': 1018 | case 'e': 1019 | case 'f': 1020 | case 'g': 1021 | case 'h': 1022 | case 'i': 1023 | case 'j': 1024 | case 'k': 1025 | case 'l': 1026 | case 'm': 1027 | case 'n': 1028 | case 'o': 1029 | case 'p': 1030 | case 'q': 1031 | case 'r': 1032 | case 's': 1033 | case 't': 1034 | case 'u': 1035 | case 'v': 1036 | case 'w': 1037 | case 'x': 1038 | case 'y': 1039 | case 'z': goto yy86; 1040 | case ':': 1041 | case '@': goto yy80; 1042 | case ';': goto yy91; 1043 | default: goto yy82; 1044 | } 1045 | yy88: 1046 | ++YYCURSOR; 1047 | if (YYLIMIT == YYCURSOR) YYFILL(1); 1048 | yych = *YYCURSOR; 1049 | switch (yych) { 1050 | case '-': 1051 | case '.': 1052 | case '/': 1053 | case '0': 1054 | case '1': 1055 | case '2': 1056 | case '3': 1057 | case '4': 1058 | case '5': 1059 | case '6': 1060 | case '7': 1061 | case '8': 1062 | case '9': 1063 | case 'A': 1064 | case 'B': 1065 | case 'C': 1066 | case 'D': 1067 | case 'E': 1068 | case 'F': 1069 | case 'G': 1070 | case 'H': 1071 | case 'I': 1072 | case 'J': 1073 | case 'K': 1074 | case 'L': 1075 | case 'M': 1076 | case 'N': 1077 | case 'O': 1078 | case 'P': 1079 | case 'Q': 1080 | case 'R': 1081 | case 'S': 1082 | case 'T': 1083 | case 'U': 1084 | case 'V': 1085 | case 'W': 1086 | case 'X': 1087 | case 'Y': 1088 | case 'Z': 1089 | case '_': 1090 | case 'a': 1091 | case 'b': 1092 | case 'c': 1093 | case 'd': 1094 | case 'e': 1095 | case 'f': 1096 | case 'g': 1097 | case 'h': 1098 | case 'i': 1099 | case 'j': 1100 | case 'k': 1101 | case 'l': 1102 | case 'm': 1103 | case 'n': 1104 | case 'o': 1105 | case 'p': 1106 | case 'q': 1107 | case 'r': 1108 | case 's': 1109 | case 't': 1110 | case 'u': 1111 | case 'v': 1112 | case 'w': 1113 | case 'x': 1114 | case 'y': 1115 | case 'z': goto yy88; 1116 | case ';': goto yy90; 1117 | default: goto yy82; 1118 | } 1119 | yy90: 1120 | yych = *++YYCURSOR; 1121 | goto yy75; 1122 | yy91: 1123 | ++YYCURSOR; 1124 | yych = *YYCURSOR; 1125 | goto yy75; 1126 | } 1127 | #line 155 "amqp_conf.re.c" 1128 | 1129 | 1130 | _bool: 1131 | s->ptok=cursor; 1132 | 1133 | #line 1134 "amqp_conf.c" 1134 | { 1135 | YYCTYPE yych; 1136 | if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); 1137 | yych = *YYCURSOR; 1138 | switch (yych) { 1139 | case '0': goto yy98; 1140 | case '1': goto yy96; 1141 | case ';': goto yy100; 1142 | case 'o': goto yy94; 1143 | default: goto yy102; 1144 | } 1145 | yy94: 1146 | yych = *(YYMARKER = ++YYCURSOR); 1147 | switch (yych) { 1148 | case 'f': goto yy103; 1149 | case 'n': goto yy105; 1150 | default: goto yy95; 1151 | } 1152 | yy95: 1153 | #line 167 "amqp_conf.re.c" 1154 | { goto _bool; } 1155 | #line 1156 "amqp_conf.c" 1156 | yy96: 1157 | ++YYCURSOR; 1158 | #line 162 "amqp_conf.re.c" 1159 | { RET(101); } 1160 | #line 1161 "amqp_conf.c" 1161 | yy98: 1162 | ++YYCURSOR; 1163 | #line 163 "amqp_conf.re.c" 1164 | { RET(102); } 1165 | #line 1166 "amqp_conf.c" 1166 | yy100: 1167 | ++YYCURSOR; 1168 | #line 165 "amqp_conf.re.c" 1169 | { goto std; } 1170 | #line 1171 "amqp_conf.c" 1171 | yy102: 1172 | yych = *++YYCURSOR; 1173 | goto yy95; 1174 | yy103: 1175 | yych = *++YYCURSOR; 1176 | switch (yych) { 1177 | case 'f': goto yy107; 1178 | default: goto yy104; 1179 | } 1180 | yy104: 1181 | YYCURSOR = YYMARKER; 1182 | goto yy95; 1183 | yy105: 1184 | ++YYCURSOR; 1185 | #line 160 "amqp_conf.re.c" 1186 | { RET( 101); } 1187 | #line 1188 "amqp_conf.c" 1188 | yy107: 1189 | ++YYCURSOR; 1190 | #line 161 "amqp_conf.re.c" 1191 | { RET( 102); } 1192 | #line 1193 "amqp_conf.c" 1193 | } 1194 | #line 169 "amqp_conf.re.c" 1195 | 1196 | 1197 | lparam: 1198 | s->ptok=cursor; 1199 | 1200 | #line 1201 "amqp_conf.c" 1201 | { 1202 | YYCTYPE yych; 1203 | if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); 1204 | yych = *YYCURSOR; 1205 | switch (yych) { 1206 | case ';': goto yy118; 1207 | case 'a': goto yy114; 1208 | case 'c': goto yy113; 1209 | case 'd': goto yy117; 1210 | case 'e': goto yy111; 1211 | case 'n': goto yy116; 1212 | case 'w': goto yy115; 1213 | default: goto yy120; 1214 | } 1215 | yy111: 1216 | yych = *(YYMARKER = ++YYCURSOR); 1217 | switch (yych) { 1218 | case 'r': goto yy152; 1219 | default: goto yy112; 1220 | } 1221 | yy112: 1222 | #line 183 "amqp_conf.re.c" 1223 | { goto lparam; } 1224 | #line 1225 "amqp_conf.c" 1225 | yy113: 1226 | yych = *(YYMARKER = ++YYCURSOR); 1227 | switch (yych) { 1228 | case 'o': goto yy145; 1229 | default: goto yy112; 1230 | } 1231 | yy114: 1232 | yych = *(YYMARKER = ++YYCURSOR); 1233 | switch (yych) { 1234 | case 'l': goto yy140; 1235 | default: goto yy112; 1236 | } 1237 | yy115: 1238 | yych = *(YYMARKER = ++YYCURSOR); 1239 | switch (yych) { 1240 | case 'a': goto yy133; 1241 | default: goto yy112; 1242 | } 1243 | yy116: 1244 | yych = *(YYMARKER = ++YYCURSOR); 1245 | switch (yych) { 1246 | case 'o': goto yy127; 1247 | default: goto yy112; 1248 | } 1249 | yy117: 1250 | yych = *(YYMARKER = ++YYCURSOR); 1251 | switch (yych) { 1252 | case 'e': goto yy121; 1253 | default: goto yy112; 1254 | } 1255 | yy118: 1256 | ++YYCURSOR; 1257 | #line 181 "amqp_conf.re.c" 1258 | { goto std; } 1259 | #line 1260 "amqp_conf.c" 1260 | yy120: 1261 | yych = *++YYCURSOR; 1262 | goto yy112; 1263 | yy121: 1264 | yych = *++YYCURSOR; 1265 | switch (yych) { 1266 | case 'b': goto yy123; 1267 | default: goto yy122; 1268 | } 1269 | yy122: 1270 | YYCURSOR = YYMARKER; 1271 | goto yy112; 1272 | yy123: 1273 | yych = *++YYCURSOR; 1274 | switch (yych) { 1275 | case 'u': goto yy124; 1276 | default: goto yy122; 1277 | } 1278 | yy124: 1279 | yych = *++YYCURSOR; 1280 | switch (yych) { 1281 | case 'g': goto yy125; 1282 | default: goto yy122; 1283 | } 1284 | yy125: 1285 | ++YYCURSOR; 1286 | #line 179 "amqp_conf.re.c" 1287 | { RET(6); } 1288 | #line 1289 "amqp_conf.c" 1289 | yy127: 1290 | yych = *++YYCURSOR; 1291 | switch (yych) { 1292 | case 't': goto yy128; 1293 | default: goto yy122; 1294 | } 1295 | yy128: 1296 | yych = *++YYCURSOR; 1297 | switch (yych) { 1298 | case 'i': goto yy129; 1299 | default: goto yy122; 1300 | } 1301 | yy129: 1302 | yych = *++YYCURSOR; 1303 | switch (yych) { 1304 | case 'c': goto yy130; 1305 | default: goto yy122; 1306 | } 1307 | yy130: 1308 | yych = *++YYCURSOR; 1309 | switch (yych) { 1310 | case 'e': goto yy131; 1311 | default: goto yy122; 1312 | } 1313 | yy131: 1314 | ++YYCURSOR; 1315 | #line 178 "amqp_conf.re.c" 1316 | { RET(5); } 1317 | #line 1318 "amqp_conf.c" 1318 | yy133: 1319 | yych = *++YYCURSOR; 1320 | switch (yych) { 1321 | case 'r': goto yy134; 1322 | default: goto yy122; 1323 | } 1324 | yy134: 1325 | yych = *++YYCURSOR; 1326 | switch (yych) { 1327 | case 'n': goto yy135; 1328 | default: goto yy122; 1329 | } 1330 | yy135: 1331 | yych = *++YYCURSOR; 1332 | switch (yych) { 1333 | case 'i': goto yy136; 1334 | default: goto yy122; 1335 | } 1336 | yy136: 1337 | yych = *++YYCURSOR; 1338 | switch (yych) { 1339 | case 'n': goto yy137; 1340 | default: goto yy122; 1341 | } 1342 | yy137: 1343 | yych = *++YYCURSOR; 1344 | switch (yych) { 1345 | case 'g': goto yy138; 1346 | default: goto yy122; 1347 | } 1348 | yy138: 1349 | ++YYCURSOR; 1350 | #line 177 "amqp_conf.re.c" 1351 | { RET(4); } 1352 | #line 1353 "amqp_conf.c" 1353 | yy140: 1354 | yych = *++YYCURSOR; 1355 | switch (yych) { 1356 | case 'e': goto yy141; 1357 | default: goto yy122; 1358 | } 1359 | yy141: 1360 | yych = *++YYCURSOR; 1361 | switch (yych) { 1362 | case 'r': goto yy142; 1363 | default: goto yy122; 1364 | } 1365 | yy142: 1366 | yych = *++YYCURSOR; 1367 | switch (yych) { 1368 | case 't': goto yy143; 1369 | default: goto yy122; 1370 | } 1371 | yy143: 1372 | ++YYCURSOR; 1373 | #line 176 "amqp_conf.re.c" 1374 | { RET(3); } 1375 | #line 1376 "amqp_conf.c" 1376 | yy145: 1377 | yych = *++YYCURSOR; 1378 | switch (yych) { 1379 | case 'n': goto yy146; 1380 | default: goto yy122; 1381 | } 1382 | yy146: 1383 | yych = *++YYCURSOR; 1384 | switch (yych) { 1385 | case 't': goto yy147; 1386 | default: goto yy122; 1387 | } 1388 | yy147: 1389 | yych = *++YYCURSOR; 1390 | switch (yych) { 1391 | case 'e': goto yy148; 1392 | default: goto yy122; 1393 | } 1394 | yy148: 1395 | yych = *++YYCURSOR; 1396 | switch (yych) { 1397 | case 'n': goto yy149; 1398 | default: goto yy122; 1399 | } 1400 | yy149: 1401 | yych = *++YYCURSOR; 1402 | switch (yych) { 1403 | case 't': goto yy150; 1404 | default: goto yy122; 1405 | } 1406 | yy150: 1407 | ++YYCURSOR; 1408 | #line 175 "amqp_conf.re.c" 1409 | { RET(2); } 1410 | #line 1411 "amqp_conf.c" 1411 | yy152: 1412 | yych = *++YYCURSOR; 1413 | switch (yych) { 1414 | case 'r': goto yy153; 1415 | default: goto yy122; 1416 | } 1417 | yy153: 1418 | yych = *++YYCURSOR; 1419 | switch (yych) { 1420 | case 'o': goto yy154; 1421 | default: goto yy122; 1422 | } 1423 | yy154: 1424 | yych = *++YYCURSOR; 1425 | switch (yych) { 1426 | case 'r': goto yy155; 1427 | default: goto yy122; 1428 | } 1429 | yy155: 1430 | ++YYCURSOR; 1431 | #line 174 "amqp_conf.re.c" 1432 | { RET(1); } 1433 | #line 1434 "amqp_conf.c" 1434 | } 1435 | #line 185 "amqp_conf.re.c" 1436 | 1437 | 1438 | 1439 | ip_param: 1440 | s->ptok=cursor; 1441 | ret = 100; 1442 | 1443 | #line 1444 "amqp_conf.c" 1444 | { 1445 | YYCTYPE yych; 1446 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); 1447 | yych = *YYCURSOR; 1448 | switch (yych) { 1449 | case '.': 1450 | case '0': 1451 | case '1': 1452 | case '2': 1453 | case '3': 1454 | case '4': 1455 | case '5': 1456 | case '6': 1457 | case '7': 1458 | case ':': goto yy159; 1459 | case ';': goto yy161; 1460 | default: goto yy163; 1461 | } 1462 | yy159: 1463 | yych = *(YYMARKER = ++YYCURSOR); 1464 | switch (yych) { 1465 | case '.': 1466 | case '0': 1467 | case '1': 1468 | case '2': 1469 | case '3': 1470 | case '4': 1471 | case '5': 1472 | case '6': 1473 | case '7': 1474 | case ':': 1475 | case ';': goto yy166; 1476 | default: goto yy160; 1477 | } 1478 | yy160: 1479 | #line 193 "amqp_conf.re.c" 1480 | { goto ip_param; } 1481 | #line 1482 "amqp_conf.c" 1482 | yy161: 1483 | ++YYCURSOR; 1484 | yy162: 1485 | #line 192 "amqp_conf.re.c" 1486 | { RET(ret); } 1487 | #line 1488 "amqp_conf.c" 1488 | yy163: 1489 | yych = *++YYCURSOR; 1490 | goto yy160; 1491 | yy164: 1492 | yych = *++YYCURSOR; 1493 | goto yy162; 1494 | yy165: 1495 | ++YYCURSOR; 1496 | if (YYLIMIT == YYCURSOR) YYFILL(1); 1497 | yych = *YYCURSOR; 1498 | yy166: 1499 | switch (yych) { 1500 | case '.': 1501 | case '0': 1502 | case '1': 1503 | case '2': 1504 | case '3': 1505 | case '4': 1506 | case '5': 1507 | case '6': 1508 | case '7': 1509 | case ':': goto yy165; 1510 | case ';': goto yy164; 1511 | default: goto yy167; 1512 | } 1513 | yy167: 1514 | YYCURSOR = YYMARKER; 1515 | goto yy160; 1516 | } 1517 | #line 194 "amqp_conf.re.c" 1518 | 1519 | 1520 | dparam: 1521 | s->ptok=cursor; 1522 | ret = 200; 1523 | 1524 | #line 1525 "amqp_conf.c" 1525 | { 1526 | YYCTYPE yych; 1527 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); 1528 | yych = *YYCURSOR; 1529 | switch (yych) { 1530 | case '0': 1531 | case '1': 1532 | case '2': 1533 | case '3': 1534 | case '4': 1535 | case '5': 1536 | case '6': 1537 | case '7': 1538 | case '8': 1539 | case '9': goto yy170; 1540 | case ';': goto yy172; 1541 | default: goto yy174; 1542 | } 1543 | yy170: 1544 | yych = *(YYMARKER = ++YYCURSOR); 1545 | switch (yych) { 1546 | case '0': 1547 | case '1': 1548 | case '2': 1549 | case '3': 1550 | case '4': 1551 | case '5': 1552 | case '6': 1553 | case '7': 1554 | case '8': 1555 | case '9': goto yy176; 1556 | case ';': goto yy175; 1557 | default: goto yy171; 1558 | } 1559 | yy171: 1560 | #line 201 "amqp_conf.re.c" 1561 | { goto dparam; } 1562 | #line 1563 "amqp_conf.c" 1563 | yy172: 1564 | ++YYCURSOR; 1565 | yy173: 1566 | #line 200 "amqp_conf.re.c" 1567 | { RET(ret); } 1568 | #line 1569 "amqp_conf.c" 1569 | yy174: 1570 | yych = *++YYCURSOR; 1571 | goto yy171; 1572 | yy175: 1573 | yych = *++YYCURSOR; 1574 | goto yy173; 1575 | yy176: 1576 | ++YYCURSOR; 1577 | if (YYLIMIT == YYCURSOR) YYFILL(1); 1578 | yych = *YYCURSOR; 1579 | switch (yych) { 1580 | case '0': 1581 | case '1': 1582 | case '2': 1583 | case '3': 1584 | case '4': 1585 | case '5': 1586 | case '6': 1587 | case '7': 1588 | case '8': 1589 | case '9': goto yy176; 1590 | case ';': goto yy175; 1591 | default: goto yy178; 1592 | } 1593 | yy178: 1594 | YYCURSOR = YYMARKER; 1595 | goto yy171; 1596 | } 1597 | #line 202 "amqp_conf.re.c" 1598 | 1599 | 1600 | 1601 | unixcomment: 1602 | 1603 | #line 1604 "amqp_conf.c" 1604 | { 1605 | YYCTYPE yych; 1606 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); 1607 | yych = *YYCURSOR; 1608 | switch (yych) { 1609 | case 0x0A: goto yy183; 1610 | case 0x0D: goto yy181; 1611 | default: goto yy185; 1612 | } 1613 | yy181: 1614 | ++YYCURSOR; 1615 | switch ((yych = *YYCURSOR)) { 1616 | case 0x0A: goto yy186; 1617 | default: goto yy182; 1618 | } 1619 | yy182: 1620 | #line 208 "amqp_conf.re.c" 1621 | { goto unixcomment; } 1622 | #line 1623 "amqp_conf.c" 1623 | yy183: 1624 | ++YYCURSOR; 1625 | yy184: 1626 | #line 207 "amqp_conf.re.c" 1627 | { s->line++; goto std; } 1628 | #line 1629 "amqp_conf.c" 1629 | yy185: 1630 | yych = *++YYCURSOR; 1631 | goto yy182; 1632 | yy186: 1633 | ++YYCURSOR; 1634 | yych = *YYCURSOR; 1635 | goto yy184; 1636 | } 1637 | #line 209 "amqp_conf.re.c" 1638 | 1639 | 1640 | comment: 1641 | 1642 | #line 1643 "amqp_conf.c" 1643 | { 1644 | YYCTYPE yych; 1645 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); 1646 | yych = *YYCURSOR; 1647 | switch (yych) { 1648 | case 0x0A: goto yy191; 1649 | case '*': goto yy189; 1650 | default: goto yy193; 1651 | } 1652 | yy189: 1653 | ++YYCURSOR; 1654 | switch ((yych = *YYCURSOR)) { 1655 | case '/': goto yy194; 1656 | default: goto yy190; 1657 | } 1658 | yy190: 1659 | #line 221 "amqp_conf.re.c" 1660 | { goto comment; } 1661 | #line 1662 "amqp_conf.c" 1662 | yy191: 1663 | ++YYCURSOR; 1664 | #line 216 "amqp_conf.re.c" 1665 | { 1666 | if(cursor == s->eof) RET(EOI); 1667 | s->tok = s->pos = cursor; s->line++; 1668 | goto comment; 1669 | } 1670 | #line 1671 "amqp_conf.c" 1671 | yy193: 1672 | yych = *++YYCURSOR; 1673 | goto yy190; 1674 | yy194: 1675 | ++YYCURSOR; 1676 | #line 213 "amqp_conf.re.c" 1677 | { goto std; } 1678 | #line 1679 "amqp_conf.c" 1679 | } 1680 | #line 222 "amqp_conf.re.c" 1681 | 1682 | } 1683 | 1684 | 1685 | 1686 | -------------------------------------------------------------------------------- /amqp_conf.re.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #define EOI 0 10 | 11 | //typedef unsigned int uint; 12 | typedef unsigned char uchar; 13 | 14 | #define BSIZE 8192 15 | 16 | #define YYCTYPE uchar 17 | #define YYCURSOR cursor 18 | #define YYLIMIT s->lim 19 | #define YYMARKER s->ptr 20 | #define YYFILL(n) {cursor = fill(s, cursor);} 21 | 22 | #define RET(i) {s->cur = cursor; return i;} 23 | 24 | #include "amqp-rest.h" 25 | 26 | unsigned char *fill(Scanner *s, uchar *cursor){ 27 | if(!s->eof) { 28 | unsigned int cnt = s->tok - s->bot; 29 | if(cnt){ 30 | memcpy(s->bot, s->tok, s->lim - s->tok); 31 | s->tok = s->bot; 32 | s->ptr -= cnt; 33 | cursor -= cnt; 34 | s->pos -= cnt; 35 | s->lim -= cnt; 36 | } 37 | if((s->top - s->lim) < BSIZE){ 38 | unsigned char *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar)); 39 | memcpy(buf, s->tok, s->lim - s->tok); 40 | s->tok = buf; 41 | s->ptr = &buf[s->ptr - s->bot]; 42 | cursor = &buf[cursor - s->bot]; 43 | s->pos = &buf[s->pos - s->bot]; 44 | s->lim = &buf[s->lim - s->bot]; 45 | s->top = &s->lim[BSIZE]; 46 | free(s->bot); 47 | s->bot = buf; 48 | } 49 | if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){ 50 | s->eof = &s->lim[cnt]; *(s->eof)++ = '\n'; 51 | } 52 | s->lim += cnt; 53 | } 54 | return cursor; 55 | } 56 | 57 | int scan(Scanner *s){ 58 | unsigned char *cursor = s->cur; 59 | int ret=0; 60 | std: 61 | s->tok = cursor; 62 | /*!re2c 63 | any = [\000-\377]; 64 | O = [0-7]; 65 | D = [0-9]; 66 | L = [a-zA-Z_]; 67 | H = [a-fA-F0-9]; 68 | E = [Ee] [+-]? D+; 69 | FS = [fFlL]; 70 | IS = [uUlL]*; 71 | ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+); 72 | EXPR = [0-9a-zA-Z_]; 73 | PATH = [0-9a-zA-Z_] | "." | "/" | "-"; 74 | CONNSTR = [0-9a-zA-Z_] | (".") | ("/") | (":") | ("@"); 75 | IP = [0-7] | (".") | (":")? ; 76 | NL = "\r"? "\n" ; 77 | TAB = "\t"; 78 | */ 79 | 80 | /*!re2c 81 | 82 | "/*" { goto comment; } 83 | "#" { goto unixcomment; } 84 | 85 | "daemon" { 86 | s->parm = 1; 87 | goto _bool; 88 | } 89 | 90 | "logfile" { 91 | s->parm = 2; 92 | goto param; 93 | } 94 | 95 | "log_level" { 96 | s->parm = 5; 97 | goto lparam; 98 | } 99 | "port" { 100 | s->parm = 3; 101 | goto dparam; 102 | } 103 | 104 | "http" { 105 | s->parm = 6; 106 | goto ip_param; 107 | } 108 | "amqp" { 109 | s->parm = 4; 110 | goto param; 111 | } 112 | 113 | "pidfile" { 114 | s->parm = 7; 115 | goto param; 116 | } 117 | 118 | 119 | 120 | [\r\v\f]+ { RET(8912); goto std; } 121 | 122 | ";" { goto std; } 123 | " " { goto std; } 124 | "\t" { goto std; } 125 | 126 | NL 127 | { 128 | if(cursor == s->eof) RET(EOI); 129 | s->pos = cursor; s->line++; 130 | goto std; 131 | } 132 | 133 | any 134 | { 135 | printf("unexpected character: %c line %d \n", *s->tok, s->line); 136 | goto std; 137 | } 138 | */ 139 | //s->tok = cursor; s->parm =3; goto param; 140 | //(PATH)*";" { RET(2001); } 141 | // 142 | 143 | 144 | 145 | param: 146 | s->ptok=cursor; 147 | /*!re2c 148 | 149 | (PATH)* ";" { RET(303); } 150 | (CONNSTR)* ";" { RET(301 ); } 151 | (EXPR)* ";" { RET(302); } 152 | 153 | any { goto param; } 154 | 155 | */ 156 | 157 | _bool: 158 | s->ptok=cursor; 159 | /*!re2c 160 | "on" { RET( 101); } 161 | "off" { RET( 102); } 162 | "1" { RET(101); } 163 | "0" { RET(102); } 164 | 165 | ";" { goto std; } 166 | 167 | any { goto _bool; } 168 | 169 | */ 170 | 171 | lparam: 172 | s->ptok=cursor; 173 | /*!re2c 174 | "error" { RET(1); } 175 | "content" { RET(2); } 176 | "alert" { RET(3); } 177 | "warning" { RET(4); } 178 | "notice" { RET(5); } 179 | "debug" { RET(6); } 180 | 181 | ";" { goto std; } 182 | 183 | any { goto lparam; } 184 | 185 | */ 186 | 187 | ip_param: 188 | s->ptok=cursor; 189 | ret = 100; 190 | /*!re2c 191 | (IP)* ";" { RET(ret); } 192 | any { goto ip_param; } 193 | */ 194 | 195 | dparam: 196 | s->ptok=cursor; 197 | ret = 200; 198 | /*!re2c 199 | (D)* ";" { RET(ret); } 200 | any { goto dparam; } 201 | */ 202 | 203 | unixcomment: 204 | /*!re2c 205 | NL { s->line++; goto std; } 206 | any { goto unixcomment; } 207 | */ 208 | 209 | comment: 210 | /*!re2c 211 | "*/" { goto std; } 212 | 213 | "\n" 214 | { 215 | if(cursor == s->eof) RET(EOI); 216 | s->tok = s->pos = cursor; s->line++; 217 | goto comment; 218 | } 219 | any { goto comment; } 220 | */ 221 | } 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /http_handler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * http_handler.cpp 3 | * amqp-rest 4 | * 5 | * Created by Alexandre Kalendarev on 01.05.10. 6 | * 7 | */ 8 | 9 | #ifndef __HTTPHANDLER__ 10 | #define __HTTPHANDLER__ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "amqpcpp.h" 17 | #include 18 | 19 | #include "tools.c" 20 | void tolog(ctx * Ctx, int type, const char * message , ...); 21 | 22 | extern ctx Ctx; 23 | 24 | 25 | void http_finalize(struct evhttp_request *req, struct evbuffer *buf ) { 26 | evhttp_add_header(req->output_headers, "Content-type", "text/json"); 27 | evhttp_add_header(req->output_headers, "Server", "amqp-rest"); 28 | 29 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 30 | evbuffer_free(buf); 31 | } 32 | 33 | void parse_uri(const char * uri, char * name, int name_len, char * parm, int parm_len) { 34 | char * p = (char *)uri; 35 | char * pn = name; 36 | int len=0; 37 | 38 | while(*p && *p != '?' && len < name_len) { 39 | if (*p=='/') { 40 | pn=name; 41 | bzero(pn,name_len); 42 | p++; 43 | } 44 | *(pn++) =*(p++); 45 | len++; 46 | } 47 | 48 | if (!*p) 49 | return; 50 | 51 | len=0; 52 | p++; 53 | pn=parm; 54 | while(*p && len < parm_len) { 55 | *(pn++) =*(p++); 56 | len++; 57 | } 58 | 59 | } 60 | int str_escape(const char * in , char * out) { 61 | int len = 0; 62 | char * p = (char *) in; 63 | while (*p) { 64 | if (*p == '"') { 65 | *out++ = '\\'; 66 | len++; 67 | } 68 | *out++ = *p++; 69 | len++; 70 | } 71 | 72 | *out = '\0'; 73 | return len; 74 | } 75 | 76 | void sendCount(struct evhttp_request *req, char * name) { 77 | struct evbuffer *buf; 78 | 79 | buf = evbuffer_new(); 80 | if (buf == NULL) { 81 | tolog( &Ctx, LOG_STDERR, "failed to create response buffer"); 82 | } 83 | 84 | try { 85 | Ctx.queue->Declare(name); 86 | char out[64]; 87 | sprintf(out, "{\"result\": \"Ok\", \"count\": %d }\r\n", Ctx.queue->getCount() ); 88 | evbuffer_add_printf(buf, out ); 89 | 90 | } catch (AMQPException e) { 91 | tolog(&Ctx, LOG_ERROR, "error QUEUE.DECLARE: %s", e.getMessage().c_str()); 92 | tolog(&Ctx, LOG_CONTENT, " %s GET %s code:%d",*Ctx.ppa, evhttp_request_uri(req), e.getReplyCode()); 93 | evbuffer_add_printf(buf, "{\"result\": \"error\"}\r\n" ); 94 | } 95 | 96 | http_finalize( req, buf); 97 | 98 | } 99 | 100 | 101 | void sendGetAll(struct evhttp_request *req, char * name) { 102 | struct evbuffer *buf; 103 | 104 | buf = evbuffer_new(); 105 | if (buf == NULL) { 106 | tolog( &Ctx, LOG_STDERR, "failed to create response buffer"); 107 | // err(1, "failed to create response buffer"); 108 | } 109 | 110 | try { 111 | 112 | Ctx.queue->setName(name); 113 | Ctx.queue->reopen(); 114 | 115 | bool is_first=1; 116 | int count = 0; 117 | string tmp(""); 118 | char * out_buf = (char *) malloc( 131072 ); 119 | 120 | while(1) { 121 | Ctx.queue->Get(AMQP_NOACK); 122 | AMQPMessage * m = Ctx.queue->getMessage(); 123 | 124 | if ( is_first && m->getMessageCount() == -1) { 125 | evbuffer_add_printf(buf, "{\"result\": \"empty\"}\r\n" ); 126 | tolog(&Ctx, LOG_CONTENT, " %s GET %s empty 200 OK",*Ctx.ppa, evhttp_request_uri(req)); 127 | break; 128 | } 129 | 130 | if ( is_first ) { 131 | is_first = 0; 132 | count = m->getMessageCount()+1; 133 | } 134 | 135 | char * msg = m->getMessage(); 136 | string tmp2; 137 | 138 | if ( m->getMessageCount() == -1) { 139 | break; 140 | } 141 | 142 | if (!msg) { 143 | tolog(&Ctx, LOG_ERROR, "message is null"); 144 | tmp2="\""; 145 | } else { 146 | str_escape(msg, out_buf ); 147 | tmp2 = string("\"")+ out_buf; 148 | 149 | if ( m->getMessageCount() == 0) { 150 | tmp += tmp2 + "\""; 151 | } else 152 | tmp += tmp2 + "\","; 153 | } 154 | } 155 | 156 | free(out_buf); 157 | char str_count[16]; bzero(str_count,16); 158 | sprintf(str_count,"%d",count); 159 | if (!is_first){ 160 | string res = string("{\"result\": \"OK\", \"count\" : ") + str_count +string(", messages [") + tmp +string("]}\r\n"); 161 | evbuffer_add_printf(buf, res.c_str() ); 162 | tolog(&Ctx, LOG_CONTENT, " %s GET %s bytes %d 200 OK", *Ctx.ppa, evhttp_request_uri(req), res.size()); 163 | } 164 | 165 | } catch (AMQPException e) { 166 | tolog(&Ctx, LOG_ERROR, "error BASIC.GET: %s", e.getMessage().c_str()); 167 | tolog(&Ctx, LOG_CONTENT, " %s GET %s code:%d", *Ctx.ppa, evhttp_request_uri(req), e.getReplyCode()); 168 | evbuffer_add_printf(buf, "{\"result\": \"error\"}\r\n" ); 169 | } 170 | 171 | http_finalize( req, buf); 172 | } 173 | 174 | void sendGet(struct evhttp_request *req, char * name) { 175 | struct evbuffer *buf; 176 | 177 | buf = evbuffer_new(); 178 | if (buf == NULL) { 179 | tolog( &Ctx, LOG_STDERR, "failed to create response buffer"); 180 | // err(1, "failed to create response buffer"); 181 | } 182 | 183 | 184 | try { 185 | Ctx.queue->reopen(); 186 | Ctx.queue->setName(name); 187 | Ctx.queue->Get(AMQP_NOACK); 188 | AMQPMessage * m = Ctx.queue->getMessage(); 189 | 190 | if (m->getMessageCount() == -1) { 191 | evbuffer_add_printf(buf, "{\"result\": \"empty\"}\r\n" ); 192 | 193 | tolog(&Ctx, LOG_CONTENT, " %s GET %s empty 200 OK", *Ctx.ppa,evhttp_request_uri(req)); 194 | } else { 195 | 196 | char * msg = m->getMessage(); 197 | 198 | char * out_buf = (char *) malloc( 131072 ); 199 | char tmp[32]; bzero(tmp,32); 200 | 201 | if ( out_buf ) { 202 | str_escape(msg, out_buf ); 203 | sprintf(tmp,"%d", m->getMessageCount()); 204 | string out="{\"result\": \"OK\", \"message\":\""+ string(out_buf) +"\", size : "+ tmp +"}\r\n" ; 205 | tolog(&Ctx, LOG_CONTENT, " %s GET %s byte:%d 200 OK",*Ctx.ppa, evhttp_request_uri(req), strlen(msg) ); 206 | evbuffer_add_printf(buf, out.c_str()); 207 | free(out_buf); 208 | } else { 209 | tolog(&Ctx, LOG_STDERR, "malloc buf"); 210 | evbuffer_add_printf(buf, "{\"result\": \"error\"}\r\n" ); 211 | } 212 | 213 | } 214 | 215 | } catch (AMQPException e) { 216 | tolog(&Ctx, LOG_ERROR, "error BASIC.GET: %s", e.getMessage().c_str()); 217 | tolog(&Ctx, LOG_CONTENT, " %s GET %s code:%d",*Ctx.ppa, evhttp_request_uri(req), e.getReplyCode()); 218 | evbuffer_add_printf(buf, "{\"result\": \"error\"}\r\n" ); 219 | } 220 | 221 | http_finalize( req, buf); 222 | } 223 | 224 | void sendPublish(struct evhttp_request *req, char * name, char * parm) { 225 | struct evbuffer *buf; 226 | string out; 227 | 228 | buf = evbuffer_new(); 229 | if (buf == NULL) { 230 | tolog( &Ctx, LOG_STDERR, "failed to create response buffer"); 231 | // err(1, "failed to create response buffer"); 232 | } 233 | 234 | try { 235 | const char * str_len = evhttp_find_header(req->input_headers, "Content-Length"); 236 | int len = atoi(str_len); 237 | 238 | out.assign((const char *)EVBUFFER_DATA(req->input_buffer),len); 239 | 240 | Ctx.queue->reopen(); 241 | Ctx.exchange->setName(name); 242 | Ctx.exchange->Publish( out, parm ); 243 | 244 | evbuffer_add_printf(buf, "{\"result\": \"Ok\"}\r\n"); 245 | tolog(&Ctx, LOG_CONTENT, " %s POST %s bytes: %d 200 OK", *Ctx.ppa, evhttp_request_uri(req), len); 246 | 247 | 248 | } catch (AMQPException e) { 249 | tolog(&Ctx, LOG_ERROR, "error BASIC.PUBLISH: %s", e.getMessage().c_str()); 250 | tolog(&Ctx, LOG_CONTENT, " %s POST %s code:%d", *Ctx.ppa, evhttp_request_uri(req), e.getReplyCode()); 251 | evbuffer_add_printf(buf, "{\"result\": \"error\"}\r\n" ); 252 | } 253 | 254 | http_finalize( req, buf); 255 | 256 | } 257 | 258 | void http_handler(struct evhttp_request *req, void *arg) { 259 | 260 | const char * uri = evhttp_request_uri(req); 261 | char name[256]; bzero(name,256); 262 | char parm[16]; bzero(parm,16); 263 | 264 | parse_uri(uri, name, 256, parm,16); 265 | 266 | u_short port=0; 267 | bzero(Ctx.ip,16); 268 | char * pa=Ctx.ip; 269 | char ** ppa=&pa; 270 | evhttp_connection_get_peer(req->evcon, ppa, &port); 271 | Ctx.ppa=ppa; 272 | 273 | if (req->type == EVHTTP_REQ_POST) { 274 | sendPublish(req,name, parm); 275 | // evhttp_send_reply(req, HTTP_OK, "OK", buf); 276 | return; 277 | } 278 | 279 | if (req->type == EVHTTP_REQ_GET) { 280 | if (strcmp(parm,"all")==0) 281 | sendGetAll(req, name); 282 | else if (strcmp(parm,"count")==0) 283 | sendCount(req, name); 284 | else 285 | sendGet(req, name); 286 | return; 287 | } 288 | } 289 | 290 | 291 | #endif -------------------------------------------------------------------------------- /ini_parse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ini_parse.cpp 3 | * amqp-rest 4 | * 5 | * Created by Alexandre Kalendarev on 30.04.10. 6 | * 7 | */ 8 | 9 | 10 | #ifndef __PARSEINI__ 11 | #define __PARSEINI__ 12 | 13 | #include "amqp-rest.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | int ini_parse( ctx * Ctx) { 21 | 22 | Scanner in; 23 | int t; 24 | memset((char*) &in, 0, sizeof(in)); 25 | in.fd = 0; 26 | unsigned int len; 27 | 28 | in.fd = open( Ctx->confile, O_RDONLY); 29 | if (in.fd <1) { 30 | // printf("conf %s\n", Ctx->confile); 31 | perror("can't open config file"); 32 | exit(1); 33 | } 34 | 35 | bzero(Ctx,sizeof(Ctx)); 36 | Ctx->port = 80; 37 | Ctx->log_level = 1; 38 | 39 | while((t = scan(&in)) != 0){ 40 | 41 | len = in.cur-in.ptok-1; 42 | 43 | // printf("%d\t'%.*s' line=%d param=%d\n", t, in.cur - in.tok, in.tok ,in.line+1, in.parm); 44 | // printf("%d %d '%.*s' \n\n", in.cur - in.tok ,in.cur-in.ptok,len, in.ptok); 45 | 46 | switch ( in.parm ) { 47 | case 1: { 48 | if (t==101) 49 | Ctx->daemon=1; 50 | break; 51 | } 52 | case 2: { 53 | if (t==303) { 54 | Ctx->logfile = (char*)malloc(len+1); 55 | if (Ctx->logfile ==NULL) { 56 | perror("malloc logfile"); 57 | return 1; 58 | } 59 | 60 | memcpy(Ctx->logfile,in.ptok,len); 61 | *(Ctx->logfile+len)='\0'; 62 | } else { 63 | printf("WARNING: log filename parse error\n"); 64 | break; 65 | } 66 | break; 67 | } 68 | case 3: { 69 | if (t==200) { 70 | Ctx->port = atoi((const char *)in.ptok); 71 | } 72 | break; 73 | } 74 | case 4: { 75 | 76 | if (t==301) { 77 | Ctx->amqp_connect = (char*)malloc(len+1); 78 | if (Ctx->amqp_connect == NULL) { 79 | perror("WARNING: malloc amqp_connect"); 80 | return 1; 81 | } 82 | 83 | memcpy(Ctx->amqp_connect,in.ptok,len); 84 | *(Ctx->amqp_connect+len)='\0'; 85 | } else { 86 | printf("WARNING: amqp connect string parse error\n"); 87 | break; 88 | } 89 | break; 90 | } 91 | case 5: { 92 | Ctx->log_level = t; 93 | if (Ctx->log_level<1) { 94 | printf("WARNING: log level parse error\n"); 95 | Ctx->log_level=1; 96 | } 97 | break; 98 | } 99 | case 6: { 100 | if (t==100) { 101 | Ctx->bind = (char*)malloc(len+1); 102 | if (Ctx->bind == NULL) { 103 | perror("WARNING: malloc bind"); 104 | return 1; 105 | } 106 | 107 | memcpy(Ctx->bind,in.ptok,len); 108 | *(Ctx->bind+len)='\0'; 109 | } else { 110 | printf("WARNING: http IP parse error\n"); 111 | break; 112 | } 113 | break; 114 | } 115 | case 7: { 116 | if (t==303) { 117 | Ctx->pidfile = (char*)malloc(len+1); 118 | if (Ctx->pidfile ==NULL) { 119 | perror("malloc pidfile"); 120 | return 1; 121 | } 122 | 123 | memcpy(Ctx->pidfile,in.ptok,len); 124 | *(Ctx->pidfile+len)='\0'; 125 | } else { 126 | printf("WARNING: pid filename parse error\n"); 127 | break; 128 | } 129 | break; 130 | } 131 | 132 | default : { 133 | printf("WARNING: parse error\n"); 134 | break; 135 | } 136 | } 137 | in.parm = 0; 138 | } 139 | 140 | close(in.fd); 141 | 142 | if (!Ctx->logfile) { 143 | Ctx->logfile=strdup("/var/log/amqp-rest.log"); 144 | } 145 | 146 | if (!Ctx->pidfile) { 147 | Ctx->pidfile=strdup("/var/amqp-rest.pid"); 148 | } 149 | 150 | if (!Ctx->bind) { 151 | printf("ERROR: http IP error\n"); 152 | return 1; 153 | } 154 | 155 | //printf("daemon %d\n log level=%d '%s'\nport=%d %s\namqp '%s'\n", Ctx->daemon,Ctx->log_level, Ctx->logfile,Ctx->port,Ctx->bind,Ctx->amqp_connect); 156 | 157 | return 0; 158 | } 159 | 160 | 161 | void free_ctx(ctx * Ctx) { 162 | if (Ctx->logfile!=NULL) 163 | free(Ctx->logfile); 164 | 165 | if (Ctx->amqp_connect != NULL) 166 | free(Ctx->amqp_connect); 167 | 168 | if (Ctx->pidfile) { 169 | free(Ctx->pidfile); 170 | } 171 | 172 | if (Ctx->bind) { 173 | free(Ctx->bind); 174 | } 175 | 176 | 177 | } 178 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "amqpcpp.h" 6 | 7 | #include "amqp-rest.h" 8 | #include "amqp_conf.c" 9 | #include "ini_parse.c" 10 | #include "tools.c" 11 | #include "http_handler.cpp" 12 | 13 | 14 | 15 | ctx Ctx; 16 | struct evhttp *httpd; 17 | 18 | int main( int argc, const char** argv ){ 19 | 20 | struct event_base *ev_base; 21 | int res=0; 22 | int is_stop=0; 23 | 24 | if (argc > 1) { 25 | Ctx.confile = (char *) argv[1]; 26 | if (strcmp(Ctx.confile,"stop")==0) { 27 | is_stop=1; 28 | Ctx.confile = "/usr/local/etc/amqp-rest.conf"; 29 | printf( "option stop\n"); 30 | } 31 | } else 32 | Ctx.confile = "/usr/local/etc/amqp-rest.conf"; 33 | 34 | ini_parse(&Ctx); 35 | 36 | if (is_stop) { 37 | pid_t pid = pid_read(&Ctx); 38 | if (pid > 0) { 39 | kill(pid, SIGTERM); 40 | } 41 | free_ctx(&Ctx); 42 | return 0; 43 | } 44 | 45 | if (pid_exist(&Ctx)) { 46 | printf( "the pid file exist or daemon already started\n"); 47 | free_ctx(&Ctx); 48 | return 1; 49 | } 50 | 51 | if (Ctx.daemon) { 52 | res=demonize(&Ctx); 53 | if (res==-1) { 54 | free_ctx(&Ctx); 55 | return 1; 56 | } 57 | } 58 | 59 | log_open(&Ctx); 60 | res=pid_create(&Ctx); 61 | if (res) { 62 | free_ctx(&Ctx); 63 | return 1; 64 | } 65 | 66 | setSignal(); 67 | 68 | tolog(&Ctx, LOG_NOTICE, "server started" ); 69 | 70 | ev_base = event_init(); 71 | httpd = evhttp_new (ev_base); 72 | 73 | //httpd = evhttp_start(Ctx.bind, Ctx.port); 74 | if (evhttp_bind_socket (httpd, Ctx.bind, (u_short)Ctx.port )) { 75 | tolog(&Ctx, LOG_ERROR, "Failed to bind %s:%d", Ctx.bind, Ctx.port); 76 | log_close(&Ctx); 77 | free_ctx(&Ctx); 78 | exit (1); 79 | } 80 | 81 | res=0; 82 | AMQP * amqp = NULL; 83 | try { 84 | amqp = new AMQP(Ctx.amqp_connect); 85 | Ctx.queue = amqp->createQueue(); 86 | Ctx.exchange = amqp->createExchange(); 87 | 88 | } catch (AMQPException e) { 89 | tolog(&Ctx, LOG_ERROR, "amqp error %s", e.getMessage().c_str()); 90 | res=1; 91 | } 92 | 93 | if (!res) { 94 | evhttp_set_gencb(httpd, http_handler, NULL); 95 | 96 | event_base_dispatch(ev_base); 97 | evhttp_free(httpd); 98 | } 99 | 100 | delete amqp; 101 | pid_delete(&Ctx); 102 | tolog(&Ctx, LOG_NOTICE, "server finished "); 103 | log_close(&Ctx); 104 | free_ctx(&Ctx); 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /tools.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tools.c 3 | * amqp-rest 4 | * 5 | * Created by Alexandre Kalendarev on 30.04.10. 6 | * 7 | */ 8 | 9 | #ifndef __AMQPRESTTOOLS__ 10 | #define __AMQPRESTTOOLS__ 11 | #include "amqp-rest.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "ini_parse.c" 26 | #include "http_handler.cpp" 27 | 28 | 29 | 30 | extern struct evhttp *httpd; 31 | 32 | extern ctx Ctx; 33 | void 34 | log_close(ctx * Ctx) { 35 | close(Ctx->log_fd); 36 | // if (res <1 ) { 37 | // perror("can't close log file"); 38 | // } 39 | } 40 | 41 | void 42 | tolog( ctx * Ctx, int type, const char * fmt, ...) { 43 | 44 | short err=0; 45 | if (strlen(fmt)>580) { 46 | // printf( "the log message is very long"); 47 | err = 1; 48 | } 49 | 50 | // printf( "log_level=%d type=%d\n", Ctx->log_level ,type ); 51 | if (Ctx->log_level < type) return; 52 | 53 | const time_t log_time=time(0); 54 | struct tm * ts = localtime(&log_time); 55 | 56 | 57 | char * str_type=NULL; 58 | switch (type) { 59 | case LOG_NOTICE : {str_type=strdup("NOTICE "); break;} 60 | case LOG_STDERR : {str_type=strdup("STDERR "); break;} 61 | case LOG_CONTENT : {str_type=strdup("CONTENT");break;} 62 | case LOG_WARNING : {str_type=strdup("WARNING");break;} 63 | case LOG_ALERT : {str_type=strdup("ALERT ");break;} 64 | case LOG_ERROR : {str_type=strdup("ERROR ");break;} 65 | case LOG_DEBUG : {str_type=strdup("DEBUG ");break;} 66 | default : {str_type=strdup("-------");break;} 67 | } 68 | 69 | if (!str_type) { 70 | perror("strdup error"); 71 | close(Ctx->log_fd); 72 | exit(1); 73 | } 74 | 75 | char buff [512]; 76 | bzero(buff,512); 77 | char * p; 78 | 79 | sprintf(buff , "%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s:",1900+ts->tm_year,ts->tm_mon, ts->tm_mday, ts->tm_hour,ts->tm_min, ts->tm_sec,str_type); 80 | free(str_type); 81 | 82 | size_t len = strlen(buff); 83 | p=buff+len; 84 | 85 | char arg_c, * arg_s; 86 | int arg_d; 87 | va_list ap; 88 | 89 | char * pfmt = (char *)fmt; 90 | len = strlen(fmt); 91 | 92 | va_start(ap, fmt); 93 | int len2; 94 | 95 | while( len--) { 96 | *p++ = *pfmt++; 97 | if ( *pfmt != '%' ) { 98 | continue; 99 | } 100 | 101 | pfmt++; 102 | 103 | switch(*pfmt) { 104 | case 's': 105 | arg_s=va_arg(ap, char *); 106 | len2=sprintf(p, "%s",arg_s); 107 | p+=len2; 108 | break; 109 | case 'd': 110 | arg_d=va_arg(ap, int); 111 | len2=sprintf(p, "%d",arg_d); 112 | p+=len2; 113 | break; 114 | case 'x': 115 | arg_d=va_arg(ap, int); 116 | len2=sprintf(p, "%x",arg_d); 117 | p+=len2; 118 | break; 119 | } 120 | pfmt++; 121 | len -=2; 122 | } 123 | 124 | va_end(ap); 125 | 126 | len=strlen(buff); 127 | *(buff+len)='\n'; 128 | 129 | // printf("len=%d '%s'", len, buff); 130 | 131 | len2 = write(Ctx->log_fd, buff, len+1); 132 | 133 | if (len2 < 0) { 134 | fprintf(stderr, "writed %d, error %s\n",len2, strerror(errno)); 135 | close(Ctx->log_fd); 136 | exit(1); 137 | } 138 | 139 | 140 | 141 | } 142 | 143 | int pid_read(ctx * Ctx) { 144 | FILE * fd = fopen(Ctx->pidfile, "r" ); 145 | if (!fd) { 146 | perror("pid file not found"); 147 | return -1; 148 | } 149 | 150 | char buf[16]; 151 | bzero(buf,16); 152 | 153 | int res = fread(buf, 16,1, fd); 154 | if (res < 0){ 155 | perror("can't read pid file"); 156 | fclose(fd); 157 | return -1; 158 | } 159 | 160 | fclose(fd); 161 | return atoi(buf); 162 | 163 | } 164 | 165 | int pid_create(ctx * Ctx) { 166 | Ctx->pidfd = open(Ctx->pidfile, O_CREAT | O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); 167 | if (!Ctx->pidfd) { 168 | tolog(Ctx, LOG_ERROR, "can't open pid file %s", strerror(errno)); 169 | // perror("can't create pid file"); 170 | return 1; 171 | } 172 | 173 | char buf[16]; 174 | bzero(buf,16); 175 | sprintf(buf,"%ld",(long)getpid()); 176 | if (write( Ctx->pidfd,buf, strlen(buf)+1) < 1) { 177 | close(Ctx->pidfd); 178 | tolog(Ctx, LOG_ERROR, "can't write to pid file %s" , strerror(errno)); 179 | // perror("can't write to pid file"); 180 | return 1; 181 | } 182 | 183 | return 0; 184 | } 185 | 186 | int pid_delete(ctx * Ctx) { 187 | if ( close(Ctx->pidfd) < 0){ 188 | tolog(Ctx, LOG_ERROR, "can't close pid file %s", strerror(errno)); 189 | // perror("can't close pid file"); 190 | } 191 | 192 | size_t res = remove(Ctx->pidfile); 193 | if (res != 0) { 194 | tolog(Ctx, LOG_ERROR, "can't remove pid file %d" , strerror(errno)); 195 | } 196 | } 197 | 198 | int pid_exist(ctx * Ctx) { 199 | struct stat st; 200 | if (!stat(Ctx->pidfile,&st)) { 201 | return 1; 202 | } 203 | 204 | if (errno==ENOENT) 205 | return 0; 206 | 207 | return 1; 208 | } 209 | 210 | int 211 | demonize(ctx * Ctx){ 212 | 213 | int fd; 214 | 215 | /* int i; 216 | struct rlimit rl; 217 | 218 | if (getrlimit(RLIMIT_NOFILE, &rl) < 0) 219 | perror("can't get file limit"); 220 | if (rl.rlim_max == RLIM_INFINITY) 221 | rl.rlim_max = 1024; 222 | for (i = 0; i < rl.rlim_max; i++) 223 | close(i); 224 | */ 225 | 226 | switch (fork()) { 227 | case -1: 228 | perror("demonize fork failed"); 229 | return -1; 230 | 231 | case 0: 232 | break; 233 | 234 | default: 235 | free_ctx(Ctx); 236 | exit(0); 237 | } 238 | 239 | int pid = getpid(); 240 | 241 | 242 | 243 | if (setsid() == -1) { 244 | // tolog(Ctx, LOG_ERROR, "setsid() failed"); 245 | perror("setsid() failed"); 246 | return -1; 247 | } 248 | 249 | umask(0); 250 | 251 | fd = open("/dev/null", O_RDWR); 252 | if (fd == -1) { 253 | // tolog("open(\"/dev/null\") failed", LOG_ERROR, Ctx); 254 | perror("open(\"/dev/null\") failed"); 255 | return -1; 256 | } 257 | 258 | if (dup2(fd, STDIN_FILENO) == -1) { 259 | // tolog("dup2(STDIN) failed", LOG_ERROR, Ctx); 260 | perror("dup2(STDIN) failed"); 261 | return -1; 262 | } 263 | 264 | if (dup2(fd, STDOUT_FILENO) == -1) { 265 | // tolog("dup2(STDOUT) failed", LOG_ERROR, Ctx); 266 | perror("dup2(STDOUT) failed"); 267 | return -1; 268 | } 269 | 270 | if (dup2(fd, STDERR_FILENO) == -1) { 271 | tolog(Ctx, LOG_ERROR, "dup2(STDERR) failed", ""); 272 | // logs << "dup2(STDERR) failed"; 273 | return -1; 274 | } 275 | 276 | 277 | if (fd > STDERR_FILENO) { 278 | if (close(fd) == -1) { 279 | // tolog("close(fd) failed", LOG_ERROR, Ctx); 280 | perror("close(fd) failed"); 281 | return -1; 282 | } 283 | } 284 | 285 | return pid; 286 | } 287 | 288 | void 289 | signal_handler(int sig) { 290 | switch(sig) { 291 | 292 | case SIGHUP: 293 | ini_parse(&Ctx); 294 | tolog(&Ctx, LOG_ERROR, "server restarted "); 295 | evhttp_free(httpd); 296 | httpd = evhttp_start(Ctx.bind, Ctx.port); 297 | evhttp_set_gencb(httpd, http_handler, NULL); 298 | event_dispatch(); 299 | 300 | break; 301 | case SIGTERM: 302 | case SIGINT: 303 | event_loopbreak(); 304 | break; 305 | default: 306 | //syslog(LOG_WARNING, "Unhandled signal (%d) %s", strsignal(sig)); 307 | break; 308 | } 309 | } 310 | 311 | void 312 | setSignal() { 313 | signal(SIGHUP, signal_handler); 314 | signal(SIGTERM, signal_handler); 315 | signal(SIGINT, signal_handler); 316 | signal(SIGQUIT, signal_handler); 317 | } 318 | 319 | 320 | void 321 | log_open(ctx * Ctx) { 322 | Ctx->log_fd = open(Ctx->logfile,O_WRONLY|O_CREAT|O_APPEND ); 323 | if (Ctx->log_fd <1) { 324 | perror("can't open log file"); 325 | exit(1); 326 | } 327 | 328 | fchmod(Ctx->log_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); 329 | if (Ctx->log_fd <1) { 330 | perror("can't assign permission"); 331 | exit(1); 332 | } 333 | 334 | printf("fd=%d", Ctx->log_fd); 335 | } 336 | 337 | #endif --------------------------------------------------------------------------------