fcm 오픈소스에 관해 질문드립니다

-@Naver의 이미지

c++에서 fcm 서버로 푸쉬메시지를 보내고 싶어서 찾던 중 오픈소스를 발견하였습니다

오픈소스의 내용은 함수 하나가 정의되어 있었습니다.

해당 함수를 호출하여 fcm서버로 메시지를 보내는것 같습니다.

bool send_a_push_notification(const string &gcm_key, const string *node_id, const string &payload, int type)

위의 함수에서 gcm_key는 api key인것 같고..payload는 보여줄 메시지인것 같고

나머지를 모르겠습니다...
혹시 몰라서 오픈소스도 같이 올립니다.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/opensslconf.h"

// for convenience
using json = nlohmann::json;

void close_ssl(SSL *ssl , int fd){
close(fd);
SSL_shutdown(ssl);
SSL_free(ssl);
server_logger->info("Closing ssl: {}", fd);
}

bool send_a_push_notification(const string &gcm_key, const string *node_id, const string &payload, int type){

if(gcm_key.empty()) return false;
struct addrinfo hints, *result, *p;
int ret;
int fd = -1;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICSERV;
if ((ret = getaddrinfo("fcm.googleapis.com", "443", &hints, &result)) != 0){
server_logger->error("getaddrinfo failed for fcm {}", "fcm");
return false;
}

// https://fcm.googleapis.com/fcm/send
// Content-Type:application/json
// Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

for(p = result; p != NULL; p = p->ai_next){
fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (fd <0) { continue; }
if (connect(fd, p->ai_addr, p->ai_addrlen)==0) {
//print_addr_info(p);
break;
}
close(fd);
fd = -1;
}
freeaddrinfo(result);
if(fd==-1){
server_logger->error("failed to create connection to fcm");
return false;
}
/*
* create auth_key from node id
*/

SSL* ssl = SSL_new(client_ssl_ctx); /* create new SSL connection state */
SSL_set_fd(ssl, fd);
unique_ptr > fd_auto_close( ssl , boost::bind(&close_ssl, boost::placeholders::_1, fd ));//auto close on loop exit

if(SSL_connect(ssl)<0){
return false;
}
X509 *cert = SSL_get_peer_certificate(ssl);
if(!cert){
return false;
}
X509_free(cert);//i don't know why i am doing this
//websocket headers
char headers[1024];
size_t s=0;
memcpy(headers, "POST /fcm/send HTTP/1.1\r\n",25);s+=25;
memcpy(headers+s, "Content-Type: application/json\r\n", 32);s+=32;
memcpy(headers+s, "Connection: close\r\n", 19); s+=19;
memcpy(headers+s, "Host: fcm.googleapis.com\r\n", 26); s+=26;
memcpy(headers+s, "Authorization: key=", 19);s+=19;
memcpy(headers+s, &(gcm_authorization_key)[0], gcm_authorization_key.length());s+=gcm_authorization_key.length();
memcpy(headers+s, "\r\n", 2);s+=2;

json data = {
{"to", gcm_key},
{"data", {
{"type", type},
{"payload",payload}
}
},
{"notification", {
{"body" ,payload},
{"title" , "Message"}
}
}
};

string json_data = data.dump();

char content_length[10];
int n_digits = itoa(json_data.length(), content_length, 10);

memcpy(headers+s, "Content-Length: ", 16);s+=16;
memcpy(headers+s, content_length, n_digits);s+=n_digits;
memcpy(headers+s, "\r\n\r\n", 4);s+=4;

memcpy(headers+s, &json_data[0], json_data.length());s+=json_data.length();

ssize_t headers_written =0;
ERR_clear_error();
while((headers_written = SSL_write(ssl, headers, s))<0){
int ssl_err = SSL_get_error(ssl,headers_written);
if((ssl_err == SSL_ERROR_WANT_WRITE || ssl_err == SSL_ERROR_WANT_READ)){
//connection negotiation issues, connection in pending state.
ERR_clear_error();
continue;
}
break;
}
if(headers_written==s){
//read the data from socket
unique_ptr > header_buff( (char*)mem_recycler.get(2048) , boost::bind(&MemRecycler::recyle, &mem_recycler, boost::placeholders::_1, 2048));
int pret;
struct phr_header headers[100];
size_t buflen = 0, prevbuflen = 0, method_len, num_headers;

int minor_version;
int status;
const char *msg_buf;
size_t msg_buf_len;

while (true) {
/* read the request */
ERR_clear_error();
ssize_t bytes_read = SSL_read( ssl, header_buff.get() + buflen, 2048-buflen );
if (bytes_read <= 0){

if(errno!=LIBCO_POLL_TIMEOUT){
//ssl related error , handshaking in between
int ssl_err = SSL_get_error(ssl,bytes_read);
if((ssl_err == SSL_ERROR_WANT_WRITE || ssl_err == SSL_ERROR_WANT_READ)){
//connection negotiation issues, connection in pending state.
continue;
}
}
// even if timeout , we break , because it should respond in timeout
break;
}

prevbuflen = buflen;
buflen+=bytes_read;
/* parse the request */
num_headers = sizeof(headers) / sizeof(headers[0]);
pret = phr_parse_response(header_buff.get(), buflen, &minor_version , &status, &msg_buf, &msg_buf_len,
headers, &num_headers, prevbuflen);
if (pret > 0)
break; /* successfully parsed the request */
else if (pret == -1){
break;
}
if (buflen >= 2048){
break;
}
//pret == -2 continue looping.
}
if(pret>0){
return true;
}
return false;
}
return false;
}

-@Naver의 이미지

초보라서 잘모르겠습니다..
c++에서 curl이라는 것이 가능한것인가요?
curl에 대해 간략히 설명부탁드려도 될까요?

ktd2004의 이미지

위 소스 코드가 하는 일은 https(http가 아닌) 요청을 하는 소스 코드입니다.
즉, fcm 이라는 것은 특정한/정해진 packet을 https로 요청하면 되는겁니다.
curl은 https 호출해 주는 console 프로그램입니다.
fcm과 curl로 검색을 해 보시면 curl로 fcm을 테스트하는 예제들이 꽤 있을 겁니다.
그렇게 테스트를 한 후에, 직접(소스 코딩) https 호출을 socket 프로그램으로 구현해도 되겠죠.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.