基于nghttp2的APNs new API 测试(c实现)

主要为了测试api的一些特性

 

3.2 :

  发现不用带有content-length 字段也可以发送,但文档中说的是 must provide,待进一步确认

3.22:

  做了个工具,推单条的

  APNs推送的测试工具(使用新的HTTP2 api)

  

-----

 

via github:

https://github.com/wardenlym/apns2-demo

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdbool.h>
  4 #include <fcntl.h>
  5 #include <string.h>
  6 #include <errno.h>
  7 
  8 #include <sys/socket.h>
  9 #include <netdb.h>
 10 #include <netinet/in.h>
 11 #include <arpa/inet.h>
 12 #include <netinet/tcp.h>
 13 
 14 #include <sys/epoll.h>
 15 
 16 #include <openssl/ssl.h>
 17 #include <openssl/err.h>
 18 #include <openssl/bio.h>
 19 
 20 #include <nghttp2/nghttp2.h>
 21 
 22 
 23 enum {
 24     IO_NONE,
 25     WANT_READ,
 26     WANT_WRITE
 27 };
 28 
 29 #define MAKE_NV(NAME, VALUE)                                                   \
 30   {                                                                            \
 31     (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1,   \
 32         NGHTTP2_NV_FLAG_NONE                                                   \
 33   }
 34 
 35 #define MAKE_NV_CS(NAME, VALUE)                                                \
 36   {                                                                            \
 37     (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE),       \
 38         NGHTTP2_NV_FLAG_NONE                                                   \
 39   }
 40 
 41 struct connection_t {
 42     int fd;
 43     SSL_CTX *ssl_ctx;
 44     SSL *ssl;
 45     nghttp2_session *session;
 46     int want_io;
 47 };
 48 
 49 struct uri_t {
 50     const char *url;
 51     const char *prefix;
 52     const char *token;
 53     uint16_t port;
 54     const char *cert;
 55     char *path;
 56 };
 57 
 58 struct request_t {
 59     struct uri_t uri;
 60     uint8_t *data;
 61     size_t data_len;
 62 };
 63 
 64 struct loop_t {
 65     int epfd;
 66 };
 67 
 68 static void
 69 die(const char *msg)
 70 {
 71     fprintf(stderr, "FATAL: %s\n", msg);
 72     exit(EXIT_FAILURE);
 73 }
 74 
 75 static void
 76 diec(const char *msg,int i)
 77 {
 78     fprintf(stderr, "FATAL: %s %d\n", msg,i);
 79     exit(EXIT_FAILURE);
 80 }
 81 
 82 static bool
 83 file_exsit(const char *f)
 84 {
 85     return 0 == access(f, 0) ? true : (printf("file not exsit:%s\n",f),false);
 86 }
 87 
 88 static bool
 89 option_is_test(int argc, const char *arg1)
 90 {
 91     if (argc == 2 && 0 == strcmp(arg1, "test")) {
 92         return true;
 93     } else {
 94         return false;
 95     }
 96 }
 97 
 98 static bool
 99 option_is_regular(int argc, const char *token, const char *cert, const char *msg)
100 {
101     if (argc == 4 && file_exsit(cert) && (msg!=NULL)) {
102         return true;
103     } else {
104         return false;
105     }
106 }
107 
108 struct uri_t
109 make_uri(const char *url, uint16_t port, const char *prefix, const char *token ,const char *cert)
110 {
111     struct uri_t uri;
112     uri.url = url;
113     uri.port = port;
114     uri.prefix = prefix;
115     uri.token = token;
116     uri.cert = cert;
117 
118     uri.path = malloc(strlen(prefix)+strlen(token)+1);
119     memset(uri.path,0,strlen(prefix)+strlen(token)+1);
120     strcat(uri.path,prefix);
121     strcat(uri.path,token);
122     return uri;
123 }
124 
125 static void
126 init_global_library()
127 {
128     SSL_library_init();
129     SSL_load_error_strings();
130 }
131 
132 static int
133 connect_to_url(const char *url, uint16_t port)
134 {
135     int sockfd;
136     int rv;
137     struct addrinfo hints, *res, *ressave;
138     char port_str[6];
139 
140     bzero(&hints, sizeof(struct addrinfo));
141     bzero(port_str, sizeof(port_str));
142     snprintf(port_str, 6, "%d", port);
143     hints.ai_family = AF_UNSPEC;
144     hints.ai_socktype = SOCK_STREAM;
145     
146     printf("ns looking up ...\n");
147     rv = getaddrinfo(url, port_str, &hints, &res);
148     if (rv != 0) {
149         freeaddrinfo(res);
150         return -1;
151     }
152 
153     ressave = res;
154     do {
155         sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
156         if(sockfd < 0) {
157             continue;
158         }
159         struct in_addr a = ((struct sockaddr_in*)res->ai_addr)->sin_addr;
160         const char *p = inet_ntoa(a);
161         printf("connecting to : %s\n",p);
162         while ((rv = connect(sockfd, res->ai_addr, res->ai_addrlen)) == -1 &&
163                 errno == EINTR)
164             ;
165         if (0 == rv) {
166             freeaddrinfo(ressave);
167             return sockfd;
168         } else {
169             close(sockfd);
170         }
171     } while ((res = res->ai_next) != NULL);
172 
173     freeaddrinfo(ressave);
174     return -1; 
175 }
176 
177 static bool
178 socket_connect(const struct uri_t *uri, struct connection_t *conn)
179 {
180     int fd;
181     fd = connect_to_url(uri->url,uri->port);
182     if (fd > 0) {
183         conn->fd = fd;
184         printf("socket connect ok: fd=%d, host: %s:%d\n", conn->fd, uri->url, uri->port);
185         return true;
186     }
187     die("socket connect fail.");
188     return false;
189 }
190 
191 static X509*
192 read_x509_certificate(const char* path)
193 {
194     BIO  *bio = NULL;
195     X509 *x509 = NULL;
196     if (NULL == (bio = BIO_new_file(path, "r"))) {
197         return NULL;
198     }
199     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
200     BIO_free(bio);
201     return x509;
202 }
203 
204 /*
205  * Callback function for TLS NPN. Since this program only supports
206  * HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
207  * library supports, we terminate program.
208  */
209 static int
210 select_next_proto_cb(SSL *ssl, unsigned char **out,
211                      unsigned char *outlen, const unsigned char *in,
212                      unsigned int inlen, void *arg)
213 {
214     int rv;
215   /* nghttp2_select_next_protocol() selects HTTP/2 protocol the
216      nghttp2 library supports. */
217     rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
218     if (rv <= 0) {
219         die("Server did not advertise HTTP/2 protocol");
220     }
221     return SSL_TLSEXT_ERR_OK;
222 }
223 
224 static void
225 init_ssl_ctx(SSL_CTX *ssl_ctx)
226 {
227   /* Disable SSLv2 and enable all workarounds for buggy servers */
228     SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
229     SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
230     SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
231   /* Set NPN callback */
232     SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
233 }
234 
235 static bool
236 ssl_allocate(struct connection_t *conn, const char *cert)
237 {
238     int rv;
239     X509 *x509 = NULL;
240     SSL_CTX *ssl_ctx = NULL;
241     SSL *ssl = NULL;
242 
243     if (NULL == (x509 = read_x509_certificate(cert))) {
244         return false;
245     }
246 
247     ssl_ctx = SSL_CTX_new(SSLv23_client_method());
248     if (ssl_ctx == NULL) {
249         X509_free(x509);
250     }
251     init_ssl_ctx(ssl_ctx);
252     
253     rv = SSL_CTX_use_certificate(ssl_ctx, x509);
254     X509_free(x509);
255     if (rv != 1) {
256         SSL_CTX_free(ssl_ctx);
257         return false;
258     }
259 
260     rv = SSL_CTX_use_PrivateKey_file(ssl_ctx, cert, SSL_FILETYPE_PEM);
261     if (rv != 1) {
262         SSL_CTX_free(ssl_ctx);
263         return false;
264     }  
265 
266     rv = SSL_CTX_check_private_key(ssl_ctx);
267     if (rv != 1) {
268         SSL_CTX_free(ssl_ctx);
269         return false;
270     }  
271 
272     ssl = SSL_new(ssl_ctx);
273     if (ssl == NULL) {
274         SSL_CTX_free(ssl_ctx);
275         return false;
276     }    
277     
278     conn->ssl_ctx = ssl_ctx;
279     conn->ssl = ssl;
280     return true;
281 }
282 
283 static bool
284 ssl_handshake(SSL *ssl, int fd)
285 {
286     int rv;
287     if (SSL_set_fd(ssl, fd) == 0) {
288         return false;
289     }
290     ERR_clear_error();
291     rv = SSL_connect(ssl);
292     if (rv <= 0) {
293         fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
294         return false;
295     }
296     return true;
297 }
298 
299 static bool
300 ssl_connect(const struct uri_t *uri, struct connection_t *conn)
301 {
302     if (ssl_allocate(conn,uri->cert)) {
303         fprintf(stdout, "ssl allocation ok\n");
304     } else {
305         fprintf(stderr, "ssl allocation error\n");
306         return false;
307     }
308 
309     fprintf(stderr, "ssl handshaking ...\n");
310     if (ssl_handshake(conn->ssl, conn->fd)) {
311         fprintf(stderr, "ssl handshake ok\n");
312     } else {
313         fprintf(stderr, "ssl handshake error\n");
314         return false;
315     }
316     
317     printf("tls/ssl connect ok: protocol= \n");
318     return true;
319 }
320 
321 // callback impelement
322 #define _U_
323 /*
324  * The implementation of nghttp2_send_callback type. Here we write
325  * |data| with size |length| to the network and return the number of
326  * bytes actually written. See the documentation of
327  * nghttp2_send_callback for the details.
328  */
329 static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
330                              size_t length, int flags _U_, void *user_data) {
331 
332   int rv;
333   struct connection_t *conn = user_data;
334   conn->want_io = IO_NONE;
335   ERR_clear_error();
336   rv = SSL_write(conn->ssl, data, (int)length);
337   if (rv <= 0) {
338     int err = SSL_get_error(conn->ssl, rv);
339     if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
340       conn->want_io =
341           (err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
342       rv = NGHTTP2_ERR_WOULDBLOCK;
343     } else {
344       rv = NGHTTP2_ERR_CALLBACK_FAILURE;
345     }
346   }
347   return rv;
348 }
349 
350 /*
351  * The implementation of nghttp2_recv_callback type. Here we read data
352  * from the network and write them in |buf|. The capacity of |buf| is
353  * |length| bytes. Returns the number of bytes stored in |buf|. See
354  * the documentation of nghttp2_recv_callback for the details.
355  */
356 static ssize_t recv_callback(nghttp2_session *session _U_, uint8_t *buf,
357                              size_t length, int flags _U_, void *user_data) {
358 
359   struct connection_t *conn;
360   int rv;
361   conn = (struct connection_t *)user_data;
362   conn->want_io = IO_NONE;
363   ERR_clear_error();
364   rv = SSL_read(conn->ssl, buf, (int)length);
365   if (rv < 0) {
366     int err = SSL_get_error(conn->ssl, rv);
367     if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
368       conn->want_io =
369           (err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
370       rv = NGHTTP2_ERR_WOULDBLOCK;
371     } else {
372       rv = NGHTTP2_ERR_CALLBACK_FAILURE;
373     }
374   } else if (rv == 0) {
375     rv = NGHTTP2_ERR_EOF;
376   }
377   return rv;
378 }
379 
380 static int on_frame_send_callback(nghttp2_session *session,
381                                   const nghttp2_frame *frame,
382                                   void *user_data _U_) {
383   size_t i;
384   switch (frame->hd.type) {
385   case NGHTTP2_HEADERS:
386     if (nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)) {
387       const nghttp2_nv *nva = frame->headers.nva;
388       printf("[INFO] C ----------------------------> S (HEADERS)\n");
389       for (i = 0; i < frame->headers.nvlen; ++i) {
390         fwrite(nva[i].name, nva[i].namelen, 1, stdout);
391         printf(": ");
392         fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
393         printf("\n");
394       }
395     }
396     break;
397   case NGHTTP2_RST_STREAM:
398     printf("[INFO] C ----------------------------> S (RST_STREAM)\n");
399     break;
400   case NGHTTP2_GOAWAY:
401     printf("[INFO] C ----------------------------> S (GOAWAY)\n");
402     break;
403   }
404   return 0;
405 }
406 
407 static int on_frame_recv_callback(nghttp2_session *session,
408                                   const nghttp2_frame *frame,
409                                   void *user_data _U_) {
410   switch (frame->hd.type) {
411   case NGHTTP2_HEADERS:
412     if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
413       struct connection_t *conn = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
414       if (conn) {
415         printf("[INFO] C <---------------------------- S (HEADERS end)\n");
416       }
417     } else {
418     printf("other header: %d",frame->headers.cat);
419     }
420     break;
421   case NGHTTP2_RST_STREAM:
422     printf("[INFO] C <---------------------------- S (RST_STREAM)\n");
423     break;
424   case NGHTTP2_GOAWAY:
425     printf("[INFO] C <---------------------------- S (GOAWAY)\n");
426     break;
427   }
428   return 0;
429 }
430 
431 static int on_header_callback(nghttp2_session *session,
432                               const nghttp2_frame *frame,
433                               const uint8_t *name, size_t namelen,
434                               const uint8_t *value, size_t valuelen,
435                               uint8_t flags, void *user_data) {
436 
437   if (frame->hd.type == NGHTTP2_HEADERS) {
438         fwrite(name, namelen, 1, stdout);
439         printf(": ");
440         fwrite(value, valuelen, 1, stdout);
441         printf("\n");
442 
443   }
444   return 0;
445 }
446 
447 static int on_begin_headers_callback(nghttp2_session *session,
448                                                  const nghttp2_frame *frame,
449                                                  void *user_data) {
450   printf("[INFO] C <---------------------------- S (HEADERS begin)\n");
451   return 0;
452 }
453 
454 /*
455  * The implementation of nghttp2_on_stream_close_callback type. We use
456  * this function to know the response is fully received. Since we just
457  * fetch 1 resource in this program, after reception of the response,
458  * we submit GOAWAY and close the session.
459  */
460 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
461                                     uint32_t error_code _U_,
462                                     void *user_data _U_) {
463   struct connection_t *conn = nghttp2_session_get_stream_user_data(session, stream_id);
464   if (conn) {
465     int rv;
466     rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
467 
468     if (rv != 0) {
469       diec("nghttp2_session_terminate_session", rv);
470     }
471   }
472   return 0;
473 }
474 
475 /*
476  * The implementation of nghttp2_on_data_chunk_recv_callback type. We
477  * use this function to print the received response body.
478  */
479 static int on_data_chunk_recv_callback(nghttp2_session *session,
480                                        uint8_t flags _U_, int32_t stream_id,
481                                        const uint8_t *data, size_t len,
482                                        void *user_data _U_) {
483   printf("%s\n",__FUNCTION__);
484   char buf[1024] = {0};
485   memcpy(buf,data,len);
486   buf[len]=0;
487   printf("%s\n",buf);
488   return 0;
489 }
490 
491 /*
492  * Setup callback functions. nghttp2 API offers many callback
493  * functions, but most of them are optional. The send_callback is
494  * always required. Since we use nghttp2_session_recv(), the
495  * recv_callback is also required.
496  */
497 static void
498 setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
499 {
500   nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
501   nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
502   nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, on_frame_send_callback);
503   nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, on_frame_recv_callback);
504   nghttp2_session_callbacks_set_on_header_callback(callbacks,on_header_callback);
505   nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks,on_begin_headers_callback);
506   nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, on_stream_close_callback);
507   nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, on_data_chunk_recv_callback);
508 
509 }
510 
511 static bool
512 set_nghttp2_session_info(struct connection_t *conn)
513 {
514     int rv;
515     nghttp2_session_callbacks *callbacks;
516 
517     rv = nghttp2_session_callbacks_new(&callbacks);
518     if (rv != 0) {
519         fprintf(stderr, "nghttp2_session_callbacks_new");
520     }
521     setup_nghttp2_callbacks(callbacks);
522     rv = nghttp2_session_client_new(&conn->session, callbacks, conn);
523     if (rv != 0) {
524         fprintf(stderr, "nghttp2_session_client_new");
525     }
526     nghttp2_session_callbacks_del(callbacks);
527 
528     rv = nghttp2_submit_settings(conn->session, NGHTTP2_FLAG_NONE, NULL, 0);
529     if (rv != 0) {
530     fprintf(stderr, "nghttp2_submit_settings %d",rv);
531     }
532     return true;
533 }
534 
535 static struct request_t
536 make_request(struct uri_t uri, const char *msg)
537 {
538     struct request_t req;
539     req.uri = uri;
540     req.data_len = strlen(msg);
541     req.data = malloc(req.data_len);
542     memcpy(req.data, msg, req.data_len);
543     return req;
544 }
545 
546 static int
547 set_nonblocking(int fd)
548 {
549     int flags, rv;
550     while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
551         ;
552     if (flags == -1) {
553         return -1;
554     }
555     while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
556         ;
557     if (rv == -1) {
558         return -1;
559     }
560     return 0;
561 }
562 
563 static int
564 set_tcp_nodelay(int fd)
565 {
566     int val = 1;
567     if(-1 == setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val))) {
568         return -1;
569     }
570     return 0;
571 }
572 
573 ssize_t data_prd_read_callback(
574     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length,
575     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
576   struct request_t *req = source->ptr;
577   memcpy(buf,req->data,req->data_len);
578   *data_flags |= NGHTTP2_DATA_FLAG_EOF;
579 
580   printf("[INFO] C ----------------------------> S (DATA post body)\n");
581   char payload[1024];
582   memcpy(payload,req->data,req->data_len);
583   payload[req->data_len]=0;
584   printf("%s\n",payload);
585   return req->data_len;
586 }
587 
588 static int32_t
589 submit_request(struct connection_t *conn, const struct request_t* req)
590 {
591     int32_t stream_id;
592     const nghttp2_nv nva[] = {
593           MAKE_NV(":method", "POST"),
594           MAKE_NV_CS(":path", req->uri.path),
595           MAKE_NV("apns-id", "e77a3d12-bc9f-f410-a127-43f212597a9c")
596     };
597 
598     nghttp2_data_provider data_prd;
599     data_prd.source.ptr = (void*)req;
600     data_prd.read_callback = data_prd_read_callback;
601 
602     stream_id = nghttp2_submit_request(conn->session, NULL, nva,
603                                        sizeof(nva) / sizeof(nva[0]), &data_prd, conn);
604     return stream_id;
605 }
606 
607 
608 static void
609 event_loop(struct loop_t *loop, struct connection_t *conn)
610 {
611   struct epoll_event ev,events[20];
612   int epfd = loop->epfd;
613 
614   ev.data.fd = conn->fd;
615   ev.events=EPOLLIN|EPOLLOUT;
616   epoll_ctl(epfd,EPOLL_CTL_ADD,conn->fd,&ev);
617   while (nghttp2_session_want_read(conn->session) ||
618          nghttp2_session_want_write(conn->session)) {
619     int nfds=epoll_wait(epfd,events,20,-1);
620     int i;
621     for(i=0;i<nfds;++i) {
622         int rv;
623         if(events[i].events & EPOLLIN) {
624           rv = nghttp2_session_recv(conn->session);
625           if (rv != 0) {
626             diec("nghttp2_session_recv", rv);
627           }
628           ev.data.fd=events[i].data.fd;
629           ev.events = EPOLLOUT;
630           epoll_ctl(epfd,EPOLL_CTL_MOD,events[i].data.fd,&ev);
631 
632         } else if(events[i].events & EPOLLOUT) {
633           rv = nghttp2_session_send(conn->session);
634           if (rv != 0) {
635             diec("nghttp2_session_send", rv);
636           }
637           ev.data.fd=events[i].data.fd;
638           ev.events = EPOLLIN;
639           epoll_ctl(epfd,EPOLL_CTL_MOD,events[i].data.fd,&ev);
640         } else {
641         if ((events[i].events & EPOLLHUP) || (events[i].events & EPOLLERR)) {
642             epoll_ctl(epfd,EPOLL_CTL_DEL,events[i].data.fd,NULL);
643         } else {
644             printf("%s\n","epoll other");
645         }
646         }
647     }
648   }
649 }
650 
651 static bool
652 blocking_post(struct loop_t *loop, struct connection_t *conn, const struct request_t *req)
653 {
654     set_nonblocking(conn->fd);
655     set_tcp_nodelay(conn->fd);
656 
657     int32_t stream_id;
658     stream_id = submit_request(conn, req);
659     if (stream_id < 0) {
660     printf("stream id error: %d\n",stream_id);
661     return false;
662     }
663 
664     printf("[INFO] Stream ID = %d\n", stream_id);
665 
666     loop->epfd = epoll_create1(0);
667 
668     if (loop->epfd < 0) {
669     printf("epoll_create fail : %d\n", loop->epfd);
670     return false;
671     }
672 
673     /* maybe running in a thread */
674     event_loop(loop,conn);
675 
676     close(loop->epfd);
677     loop->epfd = -1;
678     printf("over.\n");
679     return true;
680 }
681 
682 static void
683 connection_cleanup(struct connection_t *conn)
684 {
685   if (conn->session &&
686       conn->ssl &&
687       conn->ssl_ctx) {
688     nghttp2_session_del(conn->session);
689     SSL_shutdown(conn->ssl);
690     SSL_free(conn->ssl);
691     SSL_CTX_free(conn->ssl_ctx);
692     shutdown(conn->fd, SHUT_WR);
693     close(conn->fd); 
694   }
695 }
696 
697 void
698 usage()
699 {
700     printf("usage: apns2demo token cert message \n");
701 }
702 
703 static void test();
704 
705 int
706 main(int argc, const char *argv[])
707 {
708     struct connection_t conn;
709     struct uri_t uri;
710     struct loop_t loop;
711     const char *msg;
712 
713     if (argc == 1) {
714         /* default: my test device info */
715         uri = make_uri("api.push.apple.com", 2197, "/3/device/",
716                "73f98e1833fa744403fb4447e0f3a054d43f433b80e48c5bcaa62b501fd0f956",
717                "1fa5281c6c1d4cf5bb0bbbe0_dis_certkey.pem");
718         msg="{\"aps\":{\"alert\":\"nghttp2 test.\",\"sound\":\"default\"}}";
719     } else if (option_is_test(argc,argv[1])) {
720         test();
721         exit(0);
722     } else if (option_is_regular(argc, argv[1], argv[2], argv[3])) {
723         /* production */
724         uri = make_uri("api.push.apple.com", 2197, "/3/device/", argv[1], argv[2]);
725         msg = argv[3];
726     } else {
727         usage();
728         exit(0);
729     }
730 
731 
732     printf("nghttp2 version: %s\n", NGHTTP2_VERSION);
733     printf("tls/ssl version: %s\n", SSL_TXT_TLSV1_2);
734 
735     init_global_library();
736     
737     socket_connect(&uri, &conn);
738     if(!ssl_connect(&uri, &conn))
739       die("ssl connect fail.");
740     set_nghttp2_session_info(&conn);
741 
742     struct request_t req = make_request(uri,msg);
743     blocking_post(&loop, &conn, &req);
744 
745     connection_cleanup(&conn);
746 
747     return 0;
748 }
749 
750 static void
751 test()
752 {
753   // bad path
754  
755   // invalid token
756 
757   // feedback
758 
759   // 目前以上几个response经我测试,行为跟官方文档完全相同,省略
760 
761 }

 

posted @ 2016-03-01 11:23  夜幕の终焉  阅读(5631)  评论(15编辑  收藏  举报