:::: MENU ::::
Posts tagged with: BASE64

임베디드 보드에서 트위터하기

이 블로그 포스트는 Twitter API Proxy 서비스인 supertweet.net를 이용해서 PC나 스마트폰이 아닌 임베디드 보드에서 트위터 메시지를 보내는 방법을 설명한다.
참조 사이트:mbed의 post to Twitter via SuperTweet 

먼저 트위터 아이디가 필요한데, 테스트를 위해 twitter.com 에서 ID를 하나 만들었다. EspressoDopio2. 참고로 내 트위터 아이디는 EspressoDopio

Supertweet.net 에 접속해서 docoment link에 가면 3가지 step으로 설명을 해 놓고 있다.
1. Sign UP/ Sign in now를 클릭해서 MyAuthAPIProxy가 계정 사용을 승인하도록 한다.
2. Basic Auth를 위한 패스워드를 설정한다. 이 password는 패스워드와 다르게 설정함.
이 설정이 되면 다음과 같이 Username이 나타다고 Secret 밑에 Show 를 클릭하면 내가 정한 password가 나타난다.


3. 이젠 임베디드 보드에서 트위터 메시지를 보내면 되는데, Twitter.com 대신에  http://api.supertweet.net 로 보내면 된다.
구체적인 방법은 http://www.supertweet.net/about/api 링크를 확인하면 되는데, 간단히 메시지 post하는 것을 설명하면…

 아래 예제는 curl를 사용해서 메세지를 보내는데, user:password는 위 테이블의 Username 즉 트위터 아이디가 되겠고, password는 Supertweet에서 설정한 password이다. 트위터 메시지는 “playing with cURL and the SuperTweet.net API” 이게 되겠다.

curl -u user:password -d “status=playing with cURL and the SuperTweet.net API” http://api.supertweet.net/1/statuses/update.xml
참고) cURL은 http://curl.haxx.se/ 에서 다운로드 가능. 윈도우 버젼도 있다.

실제 트위터에 메시지가 올라간 경우.


Wireshark로 실제 날라가는 패킷을 잡아보면 다음과 같다.

빨간색이 보낸 패킷이고 파란색이 받은 패킷이다.
보낸 패킷에서 2번째 줄이 Authorization인데, Basic 뒷 부분은 “Username:password” 가 base64로 인코딩되어 있고, 보낸 패킷의 마지막 부분의 status= 뒷부분이 보낸 메시지 이다.

따라서 임베디드 보드에서 이것을 구현을 하려면,
-. DNS: api.supertweet.net에 접속을 위해
-. HTTP Client
-. Base64 encoding 함수등이 구현이 되야 겠다.

구체적인 구현 결과물은 다음 기회에……


base64 encode & decode

base64란 64진수라는 뜻.
즉 2진수 데이터를 64진수 데이터로 변경하는 것.
예를 들면 a, b, c의 경우 ASCII값은 0x61, 0x62, 0x63이고, 2진수로 01100001, 01100010, 01100011이다
이것을 6bit씩 끊으면…. 011000  010110  001001 100011 가 되고, 각각 값은 0x18(24), 0x16(22), 0x09(9), 0x23(35)가 된다.

base64의 문자셋은 다음과 같으므로,
A~Z : 0 ~25
a~z : 26 ~51
0~9 : 52 ~ 61
+      : 62
/      : 63
위 abc는 YWJj가 된다.

만약 딱 떨어지지 않는 경우 남는 비트의 경우 6 bit 문자를 0으로 padding하고 그래도 남는 6 bit 문자는 = 으로 치환한다.

C코드


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <endian.h>
 
static const char MimeBase64[] = {
    ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’,
    ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’,
    ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’,
    ‘Y’, ‘Z’, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’,
    ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’,
    ‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’,
    ‘w’, ‘x’, ‘y’, ‘z’, ‘0’, ‘1’, ‘2’, ‘3’,
    ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘+’, ‘/’
};
 
static int DecodeMimeBase64[256] = {
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 00-0F */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 10-1F */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,  /* 20-2F */
    52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,  /* 30-3F */
    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,  /* 40-4F */
    15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,  /* 50-5F */
    -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,  /* 60-6F */
    41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,  /* 70-7F */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 80-8F */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 90-9F */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* A0-AF */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* B0-BF */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* C0-CF */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* D0-DF */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* E0-EF */
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1   /* F0-FF */
};
 
typedef union{
    struct{
        unsigned char c1,c2,c3;
    };
    struct{
        unsigned int e1:6,e2:6,e3:6,e4:6;
    };
} BF;
 
int endian = 0; // little : 0, big : 1
 
void base64e(char *src, char *result, int length){
    int i, j = 0;
    BF temp;
 
    if(endian == 0){ // little endian(intel)
        for(i = 0 ; i < length ; i = i+3, j = j+4){
            temp.c3 = src[i];
            if((i+1) > length) temp.c2 = 0x00;
            else temp.c2 = src[i+1];
            if((i+2) > length) temp.c1 = 0x00;
            else temp.c1 = src[i+2];
 
            result[j]   = MimeBase64[temp.e4];
            result[j+1] = MimeBase64[temp.e3];
            result[j+2] = MimeBase64[temp.e2];
            result[j+3] = MimeBase64[temp.e1];
 
            if((i+2) > length) result[j+2] = ‘=’;
            if((i+3) > length) result[j+3] = ‘=’;
        }
    } else { // big endian(sun)
        for(i = 0 ; i < length ; i = i+3, j = j+4){
            temp.c1 = src[i];
            if((i+1) > length) temp.c2 = 0x00;
            else temp.c2 = src[i+1];
            if((i+2) > length) temp.c3 = 0x00;
            else temp.c3 = src[i+2];
 
            result[j]   = MimeBase64[temp.e4];
            result[j+1] = MimeBase64[temp.e3];
            result[j+2] = MimeBase64[temp.e2];
            result[j+3] = MimeBase64[temp.e1];
 
            if((i+2) > length) result[j+2] = ‘=’;
            if((i+3) > length) result[j+3] = ‘=’;
        }
    }
}
 
void base64d(char *src, char *result, int *length){
    int i, j = 0, src_length, blank = 0;
    BF temp;
 
    src_length = strlen(src);
 
    if(endian == 0){ // little endian(intel)
        for(i = 0 ; i < src_length ; i = i+4, j = j+3){
            temp.e4 = DecodeMimeBase64[src[i]];
            temp.e3 = DecodeMimeBase64[src[i+1]];
            if(src[i+2] == ‘=’){
                temp.e2 = 0x00;
                blank++;
            } else temp.e2 = DecodeMimeBase64[src[i+2]];
            if(src[i+3] == ‘=’){
                temp.e1 = 0x00;
                blank++;
            } else temp.e1 = DecodeMimeBase64[src[i+3]];
 
            result[j]   = temp.c3;
            result[j+1] = temp.c2;
            result[j+2] = temp.c1;
        }
    } else { // big endian(sun)
        for(i = 0 ; i < src_length ; i = i+4, j = j+3){
            temp.e4 = DecodeMimeBase64[src[i]];
            temp.e3 = DecodeMimeBase64[src[i+1]];
            if(src[i+2] == ‘=’){
                temp.e2 = 0x00;
                blank++;
            } else temp.e2 = DecodeMimeBase64[src[i+2]];
            if(src[i+3] == ‘=’){
                temp.e1 = 0x00;
                blank++;
            } else temp.e1 = DecodeMimeBase64[src[i+3]];
 
            result[j]   = temp.c1;
            result[j+1] = temp.c2;
            result[j+2] = temp.c3;
        }
    }
    *length = j-blank;
}
 
int main(void){
    char str1[]=”테스트문자열입니다.ABCabc123,./”;
    char str2[]=”7YWM7Iqk7Yq466y47J6Q7Je07J6F64uI64ukLkFCQ2FiYzEyMywuLw==”;
    char *result;
    int src_size;
    struct timespec start,end;
 
    if (__LITTLE_ENDIAN == BYTE_ORDER) endian == 0;
    else endian == 1;
 
    src_size = strlen(str1);
    result = (char *)malloc((4 * (src_size / 3)) + (src_size % 3 ? 4 : 0) + 1);
    clock_gettime(CLOCK_REALTIME, &start);
    base64e(str1, result, src_size);
    clock_gettime(CLOCK_REALTIME, &end);
    float time_dif = (end.tv_sec – start.tv_sec) + ((end.tv_nsec – start.tv_nsec) );
    printf(“함수 수행 시간: %f\n”, time_dif);
    printf(“%s\n%s\n”,str1,result);
    free(result);
 
    src_size = strlen(str2);
    result = (char *)malloc(3 * (src_size / 4));
    base64d(str2,result,&src_size);
    printf(“%s\n%s\n길이:%d\n”,str2,result,src_size);
    free(result);
}

온라인에서 base64를 테스트 할 수 있는 사이트 : http://ostermiller.org/calc/encode.html