Apache HTTP Server Version 2.0
아파치 EBCDIC 포팅
아파치 EBCDIC 포팅 개요
아파치 웹서버는 1.3 버전때 처음으로 EBCDIC 문자집합을 기본 문자집합으로 사용하는 (비-ASCII) 메인플레임 컴퓨터로 포팅되었다.
(BS2000/OSD 운영체제를 사용하는 SIEMENS 계열 메인플레임을 말한다. 이 메인플레임 운영체제에는 현재 SVR4계열의 POSIX 하위시스템이 있다).
포팅은 처음에 다음과 같은 목적에서 시작되었다
- 이 플레폼으로도 아파치 웹서버를 포팅할 수 있다는 가능성을 보이기위해서
- (몇년 전에 포팅된) 오래된 CERN-3.0 서버를 대체할 "쓸만하고 유능한" 후계자를 찾기위해
- 이 플레폼에서 아파치의 prefork 프로세스 방식이 CERN의 accept-fork-serve 방식 보다 5배 이상 성능이 좋음을 보이기위해서.
이 문서는 포팅시 여러 설계상 결정의 이유를 설명한다.
설계 목표
EBCDIC 포팅의 목적중 하나는 새로운 서버로 전환을 유도하고
쉽게 전환할 수 있도록 가능한 (EBCDIC) CERN 서버와 호환성을
유지하는 것이다. 그래서 HTML 문서가 (이전 CERN 서버가 인식하는
유일한 형식인) ASCII와 (POSIX 하위시스템의 기본 문서 형식.
그러므로 grep
이나 sed
같은 POSIX
도구를 사용할 수 있는 현실적인 형식인) EBCDIC 중 어느 형식인지
설정할 수 있어야 한다. 현재 해결책은 아파치 서버가 중간에서
문서를 가로채서 문서의 형식을 파악하는 "가상 MIME 형식"이다
(아래 참고). 다음 버전에서는 변환해야할 모든 문서에
"ebcdic-handler"를 정의하는 방법으로 문제를 해결할 것이다.
기술적 해결책
아파치가 BUFF 자료형과 메써드를 사용하여 모든 입출력을 하므로 가장 쉬운 방법은 BUFF 처리 함수에 변환기능을 추가하는 것이다. 언제든지 변환할 수 있어야 하기때문에 BUFF 객체를 변환해야 하는지 알려주는 BUFF 표시를 추가했다. 이 표시는 HTTP 프로토콜의 여러 단계에서 변경될 수 있다:
- 요청을 받기 전에 변환 (요청과 요청헤더가 항상 ASCII 형식이기 때문에)
- 요청 내용을 받았을때 content type에 따라 변환/변환안함 (요청 내용이 ASCII 문자나 바이너리 파일인 경우 변환해야 하기때문에)
- 응답헤더를 보내기 전에 변환 (응답헤더는 항상 ASCII 형식이기때문에)
- 응답 내용을 보낼때 content type에 따라 변환/변환안함 (응답 내용이 문자 파일이거나 바이너리 파일이기때문에)
포팅에 대해서
-
소스의 변화는 두가지
#ifdef
로 구분할 수 있다:#ifdef CHARSET_EBCDIC
-
모든 EBCDIC기반 컴퓨터에 필요한 코드. 문자변환, 두 문자집합간의 연속된 문자값 차이, 어떤 HTTP 프로토콜 부분이 변환되야 하는지를 알려주는 표시 등.
#ifdef _OSD_POSIX
-
SIEMENS BS2000/OSD 메인플레임 플레폼에만 필요한 코드. BS2000/OSD 플레폼에만 필요한 헤더파일 차이와 소켓 구현 문제를 다룬다.
-
소켓 수준에서 ASCII와 EBCDIC간 변화는 (BS2000 POSIX에는 이 기능을 지원하는 소켓 옵션이 있다) HTTP 프로토콜 수준에서 전송되는 자료에 프로토콜관련 문자열과 프로토콜과 무관한 일반파일이 섞여있기때문에 의도적으로 사용하지 않았다. HTTP 프로토콜 문자열은 (
GET
요청, Header: 줄, 기타 정보 등.) 항상 ASCII 형식이고, 파일전송 부분은 (즉, GIF 그림, CGI 출력 등.) 서버가 항상 "변환하지않고 그냥" 보내야 한다. 서버 코드는 "프로토콜 문자열"과 "일반 자료"를, 문자열에는bgets()
나rvputs()
, 바이너리 자료에는bgets()
나rvputs()
함수를 사용하여 구별한다. 그러므로 무조건 모든 것을 변환하는 것은 적절하지 않다.(물론 문자파일의 경우 EBCDIC 문서를 항상 ASCII로 서비스하도록 준비해야 한다)
-
그래서 포팅에는 (컴파일러가 EBCDIC 문자열로 변환한) 서버 내부 문자열과 서버가 생성한 문서를 기본 프로토콜 수준에서 변환하는 기능이 있다. 서버 코드에 산재된 ASCII escape문자
\012
와\015
는 예외다: 이들이 이미 ASCII\n
과\r
의 바이너리 값이기때문에 ASCII로 두번 변환하면 안된다. 이 예외는 서버가 생성한 문자열에만 적용된다; 외부 EBCDIC 문서는 ASCII 줄바꿈문자를 포함하면 안된다. -
BUFF 관리함수를 사용하는 방법을 살펴본 후 나는 모든 puts/write/get/gets가 거치게되는 "ebcdic/ascii 변환 계층"을 추가하고, 동적으로 변환유무를 설정할 수 있는 변환 표시를 추가했다. 문서가 원본(파일이나 CGI 출력)에서 대상(요청한 클라이언트)으로 이동할때 항상 이 계층을 두번 지난다:
파일 -> 아파치
,아파치 -> 클라이언트
.서버는 이제 EBCDIC 형식으로 된 CGI 스크립트 출력의 헤더줄을 읽고, 나머지 스크립트 출력이 ASCII임을 알아낼 수 있다 (WWW 방문자수를 세는 프로그램과 같은 경우: 문서 내용은 GIF 그림이다). 기본 EBCDIC 형식으로 모든 헤더를 처리한다; 그런 다음 서비스할 문서의 type에 따라 서버는 문서 내용이 이미 ASCII인지 혹은 EBCDIC에서 변환을 해야 하는지 결정한다.
-
(MIME type이 text/plain, text/html 등) 내용이 일반 문자인 문서를 암묵적으로 ASCII로 변환하거나, (사용자에게 빠르게 서비스하기위해 미리 문서를 ASCII 형식으로 저장하였거나 NFS로 마운트한 디렉토리에 파일이 있는 경우) 변환없이 서비스할 수 있다.
예:
이름이
.ahtml
로 끝나는 파일을 암묵적인 변환없이 ASCIItext/html
문서로 (그리고.ascii
확장자는 ASCIItext/plain
으로) 서비스하려면 다음 지시어를 사용한다:AddType text/x-ascii-html .ahtml
AddType text/x-ascii-plain .ascii또,
text/foo
식의 MIME type을AddType
"text/x-ascii-foo
" 설정하여 "일반 ASCII"로 서비스할 수 있다. -
내용이 일반 문자가 아닌 문서는 변환없이 항상 "바이너리"로 서비스한다. 예를 들어, GIF/ZIP/AU 파일형식에 가장 적합한 선택이다. 물론 사용자는 "
rcp -b
" 바이너리 옵션을 사용하여 파일을 메인플레임 호스트로 복사했어야 한다. -
서버파싱 파일은 항상 컴퓨터가 사용하는 기본 형식으로 (즉, EBCDIC) 저장되었다고 가정하고, 처리후에 변환한다.
-
CGI 출력의 경우 CGI 스크립트가 변환이 필요한지 결정한다: 적절한 Content-Type을 설정하여, 문자파일은 변환하고, GIF 출력은 변환없이 보낼 수 있다. 우리가 포팅한 wwwcount 프로그램이 후자의 경우다.
문서 저장에 대해서
바이너리 파일
서버는 Content-Type:
이 text/
로
시작하는 않는 파일을 바이너리 파일로 간주하여
어떤 변환도 하지 않는다. 바이너리 파일에는 GIF 그림, gzip으로
압축한 파일 등이 있다.
메인플레임 호스트와 유닉스 혹은 윈도우즈 PC간에 바이너리
파일을 전송할 때는 ftp "binary" (TYPE I
) 명령어나
메인플레임 호스트에서 (유닉스 rcp
는
-b
옵션을 지원하지 않는다) rcp -b
명령어를 반드시 사용하라.
문자 문서
기본적으로 서버는 문자파일이 (즉,
Content-Type:
이 text/
로 시작하는
모든 파일) 호스트의 기본 문자집합인 EBCDIC으로 저장되었다고
가정한다.
Server Side Include 문서
SSI 문서는 현재 EBCDIC 형식으로만 저장해야 한다. 처리하기 전에 ASCII를 변환하지 않는다.
아파치 모듈의 상태
모듈 | 상태 | 비고 |
---|---|---|
core |
+ | |
mod_access |
+ | |
mod_actions |
+ | |
mod_alias |
+ | |
mod_asis |
+ | |
mod_auth |
+ | |
mod_auth_anon |
+ | |
mod_auth_dbm |
? | 자체 libdb.a 를 사용하여 |
mod_autoindex |
+ | |
mod_cern_meta |
? | |
mod_cgi |
+ | |
mod_digest |
+ | |
mod_dir |
+ | |
mod_so |
- | 공유라이브러리가 없음 |
mod_env |
+ | |
mod_example |
- | (시험 단계) |
mod_expires |
+ | |
mod_headers |
+ | |
mod_imap |
+ | |
mod_include |
+ | |
mod_info |
+ | |
mod_log_agent |
+ | |
mod_log_config |
+ | |
mod_log_referer |
+ | |
mod_mime |
+ | |
mod_mime_magic |
? | 아직 포팅안됨 |
mod_negotiation |
+ | |
mod_proxy |
+ | |
mod_rewrite |
+ | 테스트안됨 |
mod_setenvif |
+ | |
mod_speling |
+ | |
mod_status |
+ | |
mod_unique_id |
+ | |
mod_userdir |
+ | |
mod_usertrack |
? | 테스트안됨 |
제삼자가 만든 모듈의 상태
모듈 | 상태 | 비고 |
---|---|---|
mod_jserv
|
- | JAVA는 포팅중이다. |
mod_php3 |
+ | mod_php3 는 LDAP, GD, FreeType 라이브러리와
함께 잘 동작한다. |
mod_put |
? | 테스트안됨 |
mod_session |
- | 테스트안됨 |