2012. 9. 2. 01:23

해킹 캠프중 멍멍이형이 코드 오딧팅을 참가자들에게 내줬는데, 정말 많이 배운 코드이다. 


#include <syslog.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BUFLEN 16
#define WORDSIZE 2
#define DWORDSIZE WORDSIZE+WORDSIZE

void mylog(intkind, char *msg){
        // 3번 취약점, 포맷스트링
        syslog(LOG_USER | kind, msg);
}

void mycpy(char *dst, char *src){
        if(strlen(src) < BUFLEN -1)
                while(*src)
                        *dst++ = *src++;
        *dst= '\x00';
}

int main(int argc, char *argv[]){
        char buf1[16];
        char buf2[16];
        char buf3[BUFLEN];
        char *buf4;
        char *buf5;
        char buf6[16];
        char *buf7;
        int i, len;

        if(argc != 12)
                exit(0);
        
        // 1번 취약점
        // argv[1]의 길이가 17바이트 이상일 경우 NULL이 복사되지 않음
        // 즉, buf1이 NULL 없는 문자열이 되어버림        
        // 이로 인해 차후 이상작동 혹은 취약점이 발생 할 수 있음
        strncpy(buf1, argv[1], sizeof(buf1));
        len= atoi(argv[2]);
        
        if (len< 16)
                // 2번 취약점
                // integer overflow 발생
                // 예를 들어 argv[3]의 값을 -4로 줄 경우 -4=4294967296가 되어버림
                memcpy(buf2, argv[3], len);
        else {
                char *buf= malloc(len+ 20);
                if(buf){
                        // 취약점 없음
                        snprintf(buf, len+20, "String too long: %s", argv[3]);

                        // 3번 취약점, 포맷스트링 
                        mylog(LOG_ERR, buf);
                }
        }

        // 취약점 없음
        mycpy(buf3, argv[4]);
                
        // 4번 취약점
        // 위 mycpy에 의해 buf3이 가득 찰 경우 버퍼오버플로우 발생
        strncat(buf3, argv[5], sizeof(buf3)-1);

        if(fork()){
                // 취약점 없음
                execl("/bin/ls", "/bin/ls", argv[6], 0);
        }

        // filter metacharacters
        char *p;
        if(p = strchr(argv[7], '&'))
                *p = 0;
        if(p = strchr(argv[7], '`'))
                *p = 0;
        if(p = strchr(argv[7], ';'))
                *p = 0;
        if(p = strchr(argv[7], '|'))
                *p = 0;
        if(strlen(argv[7]) < 1024){
                buf4 = malloc(20 + strlen(argv[7]));
                // 취약점 없음
                sprintf(buf4, "/bin/cat %s", argv[7]);

                // 5번 취약점
                // $ 특수 문자를 이용하여 시스템 명령 실행 가능
                // > 특수 문자를 이용하여 root 권한 파일 복사 가능
                system(buf4);
        }

        // 6번 취약점
        // integer overflow + Null Pointer Dereference
        // argv[8]과 argv[9]의 길이가 각각 0x7fffffff(-1)일 경우 결과는 malloc(0)이 됨
        // 리턴 값은 0 = Null Pointer Dereference
        buf5 = malloc(strlen(argv[8]) + strlen(argv[9]) + 2);
        strcpy(buf5, argv[8]);
        strcat(buf5, argv[9]);

        // 7번 취약점, 버퍼 오버플로우
        memcpy(buf6, argv[10], strlen(argv[10]));

        // 8번 취약점, 매크로 우선순위 오류
        // #define WORDSIZE 2
        // #define DWORDSIZE WORDSIZE+WORDSIZE
        // buf7 = malloc(4 * DWORDSIZE);
        // 4*2+2=10
        buf7 = malloc(4 * DWORDSIZE);
        for(i=0; i<4; i++){
                // 총 복사 길이 : 4+4+4+4=16
                memcpy(buf7 + 4 * i, argv[11] + 4 * i, DWORDSIZE);
        }
        printf("\nGot%s, (%d) %s, %s, %s, %s, %s, %s\n", buf1, len, buf2,buf3, buf4, buf5, buf6, buf7);
}
 




1. syslog log 부분 넘어올때 format string 버그 발생.


2. /bin/cat %s 부분에 $() 으로 명령어를 변수화시켜서 실행시키는 법과 환경변수로 /bin/sh을하여 필터를 우회한후 명령어를 실행 시키는 법


3.buf3  mycpy 후 strncat 에서 buf1과 buf2를 넘치게 할수 있음


4.buf6 memcpy 로 오버플로우 발생


5. ulimit 으로 힙메모리 영역 할당메모리를 못하도록 막아놓으면 *p 변수는 스택 영역으로 잡힌다. 그리고 스택오버플로우..


6. `` /bin/ls 에  ``로 명령어 같이 삽입..


7.atoi 함수에 음수를 넣어서 메모리 할당을 하면 0xffffffff 만큼 메모리를 할당.. 때문에 memcpy에서도 메모리 오버플로우 발생




Thank`s for ashine & singi

Posted by k1rha
2012. 8. 26. 02:06

GDB 사용법


*참조도서: "유닉스 리눅스 프로그래밍 필수 유틸리티"

GDB 사용 방법

<<실행>>
GDB를 이용하기 위해서는 컴파일 과정에서 디버깅 정보를 삽입해야 한다.

    컴파일 시 옵션 'g' 이용
    $ gcc -g -o main main.c

컴파일이 정상 종료 되면 GDB를 실행한다.

    gdb [프로그램명]
    $ gdb main
    gdb [프로그램명] [프로세스PID]
    $ gdb main 1928

GDB가 정상 실행되면 터미널의 프롬프트가 (gdb)로 바뀌게 된다.

<<종료>>
종료방법에는 크게 두가지가 있다.

    ctrl + d
    (gdb) q
    (gdb) quit

<<소스보기>>
옵션에 따라 실행중인 프로그램의 소스를 다양한 방법으로 볼 수 있다.

    l(list)
    list 10
    list [함수명]
    list -  //이전 10라인을 출력한다.
    list [파일명]:[함수명]
    list [파일명]:10

list 명령어를 사용하면 소스코드가 10줄 단위로 출력된다.
다음의 명령을 통해 출력단위를 변경할 수 있다.

    set listsize 20

<<세그멘테이션 폴트가 발생했을대>>
컴파일한 프로그램을 실행했을때 segmentation fault 가 발생하여
비정상 종료되었다면 다음의 명령어를 통해 오류 지점을 확인할 수 있다.

    (gdb) r(run)

run 명령어는 GDB가 프로그램을 실행시켜 이상이 발생했을때의 파일과 지점을 출력해준다.
또한 관련 함수 또는 변수에 담긴 값을 출력하여 오류수정에 많은 도움을 준다.

오류 지점에 도달하기 전 과정을 확인하기 위해서는 다음 명령어를 이용하면 된다.

    (gdb) bt

bt명령어는 백트레이스로 프로그램 스택을 역으로 탐색한다.

<<브레이크포인트>>
브레이크포인트는 다음의 방법들을 통해 설정 가능하다.

    (GDB) b(break) [함수명]
    (GDB) break 10
    (GDB) break [파일명]:[함수명]
    (GDB) break [파일명]:10
    (GDB) break +2  //현재 행에서 2개 행 이후 브레이크포인트 설정
    (GDB) break -2  //현재 행에서 2개 행 이전 브레이크포인트 설정
    (GDB) break *0x8049000  //메모리주소에 설정(어셈블리로 디버깅시 이용)
    (GDB) break 10 if var == 0  //var 변수의 값이 0일때 10번 행에 설정

브레이크포인트의 발동 조건은 다양하게 변경 가능하다.

    (GDB) condition [N] var == 0   //var변수가 0일때 N번 브레이크포인트 동작
    (GDB) condition [N] func(i) > 5

현재 설정된 브레이크포인트의 목록은 다음의 명령으로 확인 가능하다.

    (GDB) info break

브레이크포인트는 GDB가 종료될때까지 유효하다.
따라서 필요없을때는 다음의 방법들을 통해 설정을 지운다.

    (GDB) cl(clear) [함수명]
    (GDB) clear 10
    (GDB) clear [파일명]:[함수명]
    (GDB) clear [파일명]:10
    (GDB) d   //모든 브레이크포인트 지움
    (GDB) disable br  //모든 브레이크포인트 비활성화
    (GDB) disable br 1 3  //1번, 3번 브레이크포인트 비활성화
    (GDB) ensable br  //모든 브레이크포인트 활성화
    (GDB) ensable br 1 3  //1번, 3번 브레이크포인트 활성화

<<프로그램 실행>>
프로그램의 실행은 run 명령어를 이용한다.
만일 이미 실행중일때는 재실행한다.

    (gdb) r(run)

프로그램 실행시 인자를 지정하기 위해서는 다음과 같이 이용한다.

    (gdb) run arg1 arg2

실행중인 프로그램을 종료할 때는 kill 명령어를 이용한다.

    (gdb) k(kill)

현재 실행중인 행의 수행을 멈추기 위해서는 step 명령어를 이용한다.
step 명령어는 한행씩 동작하도록 한다. next 명령어와는 함수 호출시 다른 결과를 보인다.

    (gdb) s(step)
    (gdb) step 6   //step을 6번 수행

현재 행의 실행이 멈춘상태에서 다음 행을 실행하기 위해서는

    (gdb) n(next)
    (gdb) next 6   //next를 6번 수행

만일 step명령을 이용중 루프에 빠져 나오지 못할경우에는 until 명령어를 이용한다.

    (gdb) u(until)

한행씩이 아닌 다시 연달아서 실행하기 위해서는

    (gdb) c(continue)

함수가 매우 길어 끝나는 지점으로 이동하기 위해서는 finish 명령어를 사용한다.

    (gdb) finish

함수의 남은 부부을 수행하지 않고 빠져나오기 위해서는 return 명령어를 사용한다.

    (gdb) return

return 명령어를 사용시 return 값을 임의로 지정하기 위해서는 다음과 같이 이용한다.

    (gdb) return 1234

<<와치포인트 설정>>
와치포인트는 변수값의 변화와 코드의 변화를 확인할때 편리하게 이용가능하다.

    (gdb) watch [변수명]   //변수에 값이 써질 때 브레이크
    (gdb) rwatch [변수명]  //변수의 값이 읽혀질 때 브레이크
    (gdb) awatch [변수명]  //변수에 읽기, 쓰기 경우에 브레이크

<<변수와 레지스터 값 검사>>
현재 위치한 행에서 접근 가능한 지역변수들 목록 확인

    (gdb) info locals

현재 위치한 행에서 접근 가능한 전역변수들 목록 확인

    (gdb) info variables

확인하고싶은 변수의 값을 출력하기 위해서는 print 명령어를 사용한다.

    (gdb) p(print) [변수명]  //변수의 값
    (gdb) print [함수명]   //함수의 주소 값

포인터 변수의 경우 위의 방법으로 하면 주소값만이 출력된다.
포인터 변수의 값 또는 포인터 구조체 등의 값을 보기 위해서는 * 를 붙여준다.

    (gdb) print *[변수명]

이중 포인터라면 ** 를 붙여준다.

GDB는 변수 뿐만 아니라 레지스터의 값도 확인할 수 있다.

    (gdb) print $[레지스터명]

print 명령어는 지역변수를 우선하여 보여주기 때문에
지역변수와 전역변수에서 동일한 이름을 사용할때 전역변수를 확인하기 위해서는 :: 을 이용한다.

    (gdb) print 'main.c'::[변수명]

파일명은 '따옴표' 으로 감싸야한다.

특정 함수에 있는 변수를 확인하기 위해서는

    (gdb) print [함수명]::[변수명]

print 명령어로 변수 또는 레지스터를 확인할 때는 기본적으로 10진수로 출력한다.
이를 다른 형식으로 보고싶을 때는 다음과 같은 방법을 이용한다.

    (gdb) print/t [변수명]    //2진수로
    (gdb) print/o [변수명]    //8진수로
    (gdb) print/d [변수명]    //10진수로 (int)
    (gdb) print/u [변수명]    //부호없는 10진수로 (unsigned int)
    (gdb) print/x [변수명]    //16진수로
    (gdb) print/c [변수명]    //최초 1바이트 값을 문자형으로
    (gdb) print/f [변수명]    //부동소수점값
    (gdb) print/a [변수명]    //가장 가까운 심볼의 오프셋

print 명령어는 값을 보여줄뿐 아니라 값을 설정하는 것도 가능하다.

    (gdb) print [변수명] = [값]

<<화면에 변수의 값을 자동으로 디스플레이하기>>
display 명령어를 이용하면 매 단계가 진행될때마다 자동으로 변수의 값을 출력해준다.

    (gdb) display [변수명]

display 변수를 해제하기 위해서는 undisplay 명령어를 이용한다.

    (gdb) undisplay [N]

display 역시 x,c,o 등등을 이용해 다양한 형태로 출력 가능하다.

Posted by k1rha
2012. 8. 20. 17:30

Thread - Handler 방식은 UI 쓰레드와 스케쥴링같은 효과가 안된다.

때문에 asyncTask 로 구현을 해보기로 결정! 잘되면 이어서 포스팅하겟다. 


[출처 : http://darrysea.tistory.com/25 ]


메니페스트 파일 입니다.
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.asynctask" 4 android:versionCode="1" 5 android:versionName="1.0" > 6 7 <uses-sdk android:minSdkVersion="8" /> 8 9 <application 10 android:icon="@drawable/ic_launcher" 11 android:label="@string/app_name" > 12 <activity 13 android:configChanges="orientation" 14 android:label="@string/app_name" 15 android:name=".TestAsyncTaskActivity" > 16 <intent-filter > 17 <action android:name="android.intent.action.MAIN" /> 18 19 <category android:name="android.intent.category.LAUNCHER" /> 20 </intent-filter> 21 </activity> 22 </application> 23 24 </manifest>

가운데 굵게 표시된 부분을 추가해야 한다.
이유는 저렇게 하지 않으면 화면이 회전될때 액티비티가 새로 onCreate를 수행하기 때문에 정상적인 동작이 되지 않는다.
저렇게 해주면 화면모드 전환을 액티비티에서 알아서 하겟다는 의미이다.


main.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" > 6 7 <Button 8 android:id="@+id/button1" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:text="Button" /> 12 13 <ProgressBar 14 android:id="@+id/progressBar1" 15 style="?android:attr/progressBarStyleHorizontal" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:layout_marginTop="100dp" /> 19 20 </LinearLayout>
 

TestAsyncTaskActivity.java
  1 package com.asynctask;

2 3 import android.app.*; 4 import android.os.*; 5 import android.view.*; 6 import android.view.View.OnClickListener; 7 import android.widget.*; 8 9 public class TestAsyncTaskActivity extends Activity { 10 11 Button btn; 12 ProgressBar pb; 13 14 /** Called when the activity is first created. */ 15 @Override 16 public void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.main); 19 20 btn = (Button) findViewById(R.id.button1); 21 pb = (ProgressBar) findViewById(R.id.progressBar1); 22 23 btnEvent(); 24 } 25 26 private void btnEvent() { 27 btn.setOnClickListener(new OnClickListener() { 28 29 @Override 30 public void onClick(View v) { 31 new ExampleAsyncTask().execute("1", "2", "3", "4", "5"); 32 } 33 }); 34 } 35 36 class ExampleAsyncTask extends AsyncTask<String, Integer, Long> { 37 38 @Override 39 protected void onCancelled() { 40 super.onCancelled(); 41 } 42 43 @Override 44 protected void onPostExecute(Long result) { 45 btn.setText("Thread END"); 46 super.onPostExecute(result); 47 } 48 49 @Override 50 protected void onPreExecute() { 51 btn.setText("Thread START!!!!"); 52 super.onPreExecute(); 53 } 54 55 @Override 56 protected void onProgressUpdate(Integer... values) { 57 pb.setProgress(values[0]); 58 super.onProgressUpdate(values); 59 } 60 61 @Override 62 protected Long doInBackground(String... params) { 63 long result = 0; 64 int numberOfParams = params.length; 65 66 for (int i = 0; i < numberOfParams; i++) { 67 SystemClock.sleep(1000); 68 69 publishProgress((int) (((i + 1) / (float) numberOfParams) * 100)); 70 } 71 return result; 72 } 73 } 74 }

다 해준다.
하나하나 살펴보자.
메소드 이름도 직관적이라 참 알아보기 쉽다..

39번줄 취소할때 호출되는 Callback이다.
44번줄 작업이 끝난 후 호출 되는
Callback이다.
50번줄 작업이 시작하기 전에 호출 되는 
Callback이다.
56번줄 UI Update이다.
62번줄 내부에서 하는 작업이다.



Thread / Handler와의 관계를 보자면,
Thread == 62번줄
Handler == 56번줄 + 44번줄
removeCallback == 39번줄


이라고 생각하면 될 듯 하다.


아 참고로
AsyncTask를 사용 할 때는 항상 SubClass로 구현하라는데, 이유는 찾아봐야 할것 같다. 

Posted by k1rha
2012. 8. 20. 02:08

정말 많은 시간을 찾은듯... 이렇게 잘나와 있을 줄은 몰랐음.

---------------------------------------------------------------------------

[출처 http://zetcode.com/tutorials/mysqlcapitutorial/

Inserting images into MySQL database


Some people prefer to put their images into the database, some prefer to keep them on the file system for their applications. Technical difficulties arise when we work with millions of images. Images are binary data. MySQL database has a special data type to store binary data called BLOB (Binary Large Object).

mysql> describe images;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | int(11)    | NO   | PRI |         |       |
| data  | mediumblob | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

This is the table, that we will use in our example. It can be created by the following SQL statement.

create table images(id int not null primary key, data mediumblob);
#include <my_global.h>
#include <mysql.h>

int main(int argc, char **argv)
{
  MYSQL *conn;

  int len, size;
  char data[1000*1024];
  char chunk[2*1000*1024+1];
  char query[1024*5000];

  FILE *fp;

  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);

  fp = fopen("image.png", "rb");
  size = fread(data, 1, 1024*1000, fp);

  mysql_real_escape_string(conn, chunk, data, size);

  char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";
  len = snprintf(query, sizeof(stat)+sizeof(chunk) , stat, chunk);

  mysql_real_query(conn, query, len);

  fclose(fp);
  mysql_close(conn);
}

In this example, we will insert one image into the images table. The image can be max 1 MB.

 fp = fopen("image.png", "rb");
 size = fread(data, 1, 1024*1000, fp);

Here we open the image and read it into the data array.

 mysql_real_escape_string(conn, chunk, data, size);

Binary data can obtain special characters, that might cause troubles in the statements. We must escape them. The mysql_real_escape_string() puts the encoded data into the chunk array. In theory, every character might be a special character. That's why the chunk array two times as big as the data array. The function also adds a terminating null character.

 
 char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";
 len = snprintf(query, sizeof(stat)+sizeof(chunk) , stat, chunk);

These two code lines prepare the MySQL query.

 mysql_real_query(conn, query, len);

Finally, we execute the query.

Selecting images from MySQL database

In the previous example, we have inserted an image into the database. In the following example, we will select the inserted image back from the database.

#include <my_global.h>
#include <mysql.h>

int main(int argc, char **argv)
{
  MYSQL *conn;
  MYSQL_RES *result;
  MYSQL_ROW row;

  unsigned long *lengths;
  FILE *fp;

  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);

  fp = fopen("image.png", "wb");

  mysql_query(conn, "SELECT data FROM images WHERE id=1");
  result = mysql_store_result(conn);

  row = mysql_fetch_row(result);
  lengths = mysql_fetch_lengths(result);

  fwrite(row[0], lengths[0], 1, fp);
  mysql_free_result(result);

  fclose(fp);
  mysql_close(conn);
}

In this example, we will create an image file from the database.

 fp = fopen("image.png", "wb");

We open a file for writing.

 mysql_query(conn, "SELECT data FROM images WHERE id=1");

We select an image with id 1.

 row = mysql_fetch_row(result);

The row contains raw data.

 lengths = mysql_fetch_lengths(result);

We get the length of the image.

 fwrite(row[0], lengths[0], 1, fp);

We create the image file using the fwrite() standard function call.

Posted by k1rha
2012. 8. 19. 03:52

char * buff = const_cast<char *>(test.c_str());


의 형태로 c_str() 를 통해 변환이 가능하다.


Posted by k1rha
2012. 8. 19. 02:51

jsoncpp 를 다운받아서 libsjon 을 빌더한다.

그러면 라이브러리가 생겨난다. 그걸 프로젝트에 적당한 곳에 복사하고 라이브러리 디렉토리 경로로 등록해준다. 


그리고 아래와같이 json 폴더도 적당히 복사해와서 헤더로 링크 걸어주면된다.


그렇필요 가 없다는 것을 찾았다.


아래그림을 보게되는데 JOSNCPP 의 구성방식이다.

우리는 JSON 폴더만 살포시 자신의 프로젝트 폴더로 가져와서 include 시켜주면 바로 사용이 가능하다.


참간단한건데 의외로 엄청난 삽질을 햇다. 



사용은 json에 있는 json.h를 include해서 사용한다.

  1. #include <json/json.h>

 

json.h

  1. #include "autolink.h" -> config.h
    #include "value.h" -> forwards.h
    #include "reader.h" -> features.h , value.h
    #include "writer.h" -> value.h
    #include "features.h" -> forwards.h






그리고 간혹 JSONCPP 라이브러리 충돌이 난다는 메시지가 뜰대가 있는데 필자는 이걸로 엄청난 시간을 삽질했다.


http://stackoverflow.com/questions/4917592/compiling-and-using-jsoncpp-on-visual-studio10-with-boost


결국엔 스택오버플로우사이트에서 해답을 찾앗다.

  • Multithreaded (/MT)
  • Multithreaded DLL (/MD)
  • Multithreaded Debug (/MTd)
  • Multithreaded Debug DLL (/MDd)

디버깅모드는 위와같이 4가지가 있는데 JSON 라이브러리는 활성 모드와 디버그 모드가 동일하게 디버깅 모드가 동작하고 있어야 하며 JSON 라이브러리에서는  /MT 시리즈를 선호한다.





Posted by k1rha
2012. 8. 17. 11:37

root@ubuntu:~/k1rha/python/http# python blind.py

Traceback (most recent call last):

  File "blind.py", line 1, in <module>

    import urllib.request

  File "/usr/lib/python3.2/urllib/request.py", line 88, in <module>

    import http.client

  File "/usr/lib/python3.2/http/client.py", line 69, in <module>

    import email.parser

  File "/usr/lib/python3.2/email/parser.py", line 12, in <module>

    from email.feedparser import FeedParser

  File "/usr/lib/python3.2/email/feedparser.py", line 27, in <module>

    from email import message

  File "/usr/lib/python3.2/email/message.py", line 17, in <module>

    from email import utils

  File "/usr/lib/python3.2/email/utils.py", line 28, in <module>

    import socket

  File "/root/k1rha/python/http/socket.py", line 7, in <module>

    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

AttributeError: 'module' object has no attribute 'AF_INET'

root@ubuntu:~/k1rha/python/http# 

위와같인 에러가 떴을때 아래와 같은 결과를 얻을수 있었다. 

h I found the problem, it seems I cant run socket things from my home folder ... I moved the script into a new folder and it worked.

Thanks.


즉 폴더에 소켓생성권한이 없기떄문에 다른 폴더로 옮겨 실행했다는 내용이다 필자도 비슷하게 해결봄.

Posted by k1rha
2012. 8. 17. 10:53


ILedService.h


서버1.cpp


서버2.cpp


클라이언트1.cpp


클라이언트2.cpp


클라이언트3.cpp


위파일들은 헤더를 기준으로 서버1 -> 에서 좀더 객체지향적인 서버 2가 완성되었고

클라이언트도 1-> 2 -> 3 순서로 수정되어 같은 역할을 하는 것을 좀더 OCL 에 맞추어 개발하는 방향이다.

완성코드는 아래와 같다.


========================================== [ Server ]=================================================


#include<Windows.h>

#include<iostream>

#include<conio.h>


using namespace std;

void binder_loop(void (*handler)(int,int ,int))

{


//여기서 바인더 드라이버를 Open 해서 Client 에서 오는 event를 대기합니다.

//우리는 윈도우 메세지로 흉내 내도록 하겟습니다.

while(1)

{

MSG msg;

GetMessage(&msg,0,0,0);

handler(msg.message,msg.wParam,msg.lParam);


}

}


//---------------------------------------------------------

void Ontransact(int code, int param1, int param2)

{

switch(code)

{

case 5: cout << "LED ON" <<endl; break;

case 6: cout << "LED OFF" << endl; break;

}

}


DWORD __stdcall ServerMain(void *)

{

cout << "서버시작"<< endl;

binder_loop(Ontransact);

return 0;


}

================================== [ Client ] ===================================================

#include<Windows.h>

#include<iostream>

#include<conio.h>

#include "ILedService.h"


using namespace std;


DWORD ServerID=0;


DWORD __stdcall ServerMain(void *);

//---------------------------------------------------------------

//안드로이드가 제공해주느 함수 부분

void binder_call(int code, int param1, int param2)

{


PostThreadMessage(ServerID,code,param1,param2);


}


class IBinder

{

public:

void transact(int code, int param1, int param2){

binder_call(code,param1, param2);


}

};

//서비스 이름을 인자로 받아서 해당 서비스와 통신하기 위한 바인더를 만들어주는 

//함수


IBinder * getService(char *name )

{

//드라이버를 오픈해서 통신할 수 있는 바인더를 만들어 리턴

return new IBinder;

}

class BpRefBase

{

private :

IBinder *mRemote;

public :


BpRefBase(IBinder *p) : mRemote(p) {}

IBinder * remote() { return mRemote;}


};

//proxy 제작시 - 다중 상속을 단일 상속화 한다.

template<typename INTERFACE>

class BpInterface : public INTERFACE ,public BpRefBase

{

public :

BpInterface(IBinder *p) : BpRefBase(p){} //주의!

};


template<typename INTERFACE> INTERFACE * interface_cast(IBinder *p){

return INTERFACE::asInterface(p);


}


//--------------------안드로이드 제공소스 끝 ---------------------------------

// 이제 바인더를 바로 사용하지 말고 함수 호출처럼 변경하는 클래스를 제공합니다

//

//Proxy : 함수 호출 -> RPC 코드 변경 하는 역할.

//

class BpLedService : public BpInterface<ILedService>

{

public :


BpLedService(IBinder * p) : BpInterface<ILedService>(p){}


//////////////////////////////////////////////////////////

// void LedOn(){remote()->transact(5,0,0);}

// void LedOff(){remote()->transact(6,0,0);}

// 위의 경우는 어느게 ledOn인자 LedOFF인지 숫자를 외워야한다...

// 때문에 pLed를 만든다

//////////////////////////////////////////////////////////

void LedOn(){remote()->transact(5,0,0);}

void LedOff(){remote()->transact(6,0,0);}

};


//이제 proxy 제작자는 proxy 클래스를 제공한후 반드시 asInterface 구현부를 

// 제공하기로 약속 한다.

//

ILedService * ILedService ::asInterface(IBinder *svc){

return new BpLedService(svc);

}

void ClientMain(){


IBinder * svc = getService("LedService");

//이제 바인더를 바로 사용하지 말고 __ 로 변경해서 사용합니다.

//BpLedService *pLed = new BpLedService(svc); //강한 결합

//ILedService * pLed = ILedService::asInterface(svc);//약한 결합


ILedService * pLed = interface_cast<ILedService>(svc); // 약한결합을 간지나게 바꿈 

//바인더를받아 스테틱 캐스팅느낌으로...(사실은 프락시)



while(1)

{

// getch(); svc->transact(5,0,0);

// getch(); svc->transact(6,0,0);

getch(); pLed->LedOn();

getch(); pLed->LedOff();

}


}


int main()

{

CreateThread(0,0,ServerMain,0,0,&ServerID);

Sleep(1000);

ClientMain();

getch();

}




Posted by k1rha
2012. 8. 16. 17:46

#include<iostream>


using namespace std;



///////////////////////////////////////////////////////////////////

// perfect forwarding (완벽한 전달자 문제)

////////////////////////////////////////////////////////////////////


void foo(int &a){

a+=10;

cout << "foo" << endl;

}

void goo(int a){cout << "GOO " << endl;}



//함수를 호출해주는 도구 - 바인더가 결국 함수를 가지고 있다고 다시 호출해

// 주는 것입니다.

//

template<typename F, typename ARG> void Caller(F f,const ARG &a)  //함수도 전달되고 상수도 전달되는 퍼팩트 포워딩법

{


f(a);

}


int main(){

//goo(10);

Caller(goo,10);

}


/*

int main(){

int a= 10;

//foo(a);

Caller(foo,a);

cout << a <<endl;

}


*/








Posted by k1rha
2012. 8. 16. 14:57

#include<iostream>


using namespace std;


///////////////////////////////////////////////////////////////////////////////////////////////////////////

// traits 이야기

// 1.Traints : T의 특질(특성)을 조사하는 기술 ...(template 에서 특성에 따라 받아들임이 다름을 이용하는 기술

// primary template 에서 false 를 리턴 (enum 상수가 false)

//

//////////////////////////////////////////////////////////////////////////////////////////////////////////

//


template<typename T> struct my_is_array

{

enum {size=-1}; 

enum {value = false};

};

template<typename T,int N> struct my_is_array<T [N]>

{

enum {size =N};

enum {value =true};

};

template<typename T> void foo(const T& a)

{

if(my_is_array<T>::value)

cout<<"배열 입니다" << my_is_array<T>::size <<endl;

else

cout<<"배열이 아닙니다" << endl;


}

/*

template<typename T>struct my_is_pointer

{

enum{ value = false};

};

template<typename T>struct my_is_pointer<T*>

{

enum{ value = true};

};


template<typename T>void foo(const T& a)

{

if(my_is_pointer<T>::value)

cout<< "T는 포인터 입니다"<<endl;

else

cout<<"T는 포인터가 아닙니다." << endl;


}


*/

/*

template<typename T> T Max(T a, T b)

{

//return 은 주소 비교를 할수 없기때문에.. 좀더 if 문을 넣어 똑똑하게 만들자

if(T is Pointer)

return *a < *b ? b : a;

return a< b ? b : a;


}

*/


int main()

{

//int x = 10, y = 20;

/*

Max(x,y);

Max(&x, &y);

*/


int x = 0;

int y[19];

foo(x);

foo(y);


}

Posted by k1rha