00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "avformat.h"
00032 #include "mms.h"
00033 #include "internal.h"
00034 #include "avio_internal.h"
00035 #include "libavutil/intreadwrite.h"
00036 #include "libavcodec/bytestream.h"
00037 #include "network.h"
00038 #include "url.h"
00039
00040 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address.
00041 #define LOCAL_PORT 1037 // as above.
00042
00043 typedef enum {
00044 CS_PKT_INITIAL = 0x01,
00045 CS_PKT_PROTOCOL_SELECT = 0x02,
00046 CS_PKT_MEDIA_FILE_REQUEST = 0x05,
00047 CS_PKT_START_FROM_PKT_ID = 0x07,
00048 CS_PKT_STREAM_PAUSE = 0x09,
00049 CS_PKT_STREAM_CLOSE = 0x0d,
00050 CS_PKT_MEDIA_HEADER_REQUEST = 0x15,
00051 CS_PKT_TIMING_DATA_REQUEST = 0x18,
00052 CS_PKT_USER_PASSWORD = 0x1a,
00053 CS_PKT_KEEPALIVE = 0x1b,
00054 CS_PKT_STREAM_ID_REQUEST = 0x33,
00055 } MMSCSPacketType;
00056
00058 typedef enum {
00061 SC_PKT_CLIENT_ACCEPTED = 0x01,
00062 SC_PKT_PROTOCOL_ACCEPTED = 0x02,
00063 SC_PKT_PROTOCOL_FAILED = 0x03,
00064 SC_PKT_MEDIA_PKT_FOLLOWS = 0x05,
00065 SC_PKT_MEDIA_FILE_DETAILS = 0x06,
00066 SC_PKT_HEADER_REQUEST_ACCEPTED = 0x11,
00067 SC_PKT_TIMING_TEST_REPLY = 0x15,
00068 SC_PKT_PASSWORD_REQUIRED = 0x1a,
00069 SC_PKT_KEEPALIVE = 0x1b,
00070 SC_PKT_STREAM_STOPPED = 0x1e,
00071 SC_PKT_STREAM_CHANGING = 0x20,
00072 SC_PKT_STREAM_ID_ACCEPTED = 0x21,
00077 SC_PKT_CANCEL = -1,
00078 SC_PKT_NO_DATA = -2,
00083 SC_PKT_ASF_HEADER = 0x010000,
00084 SC_PKT_ASF_MEDIA = 0x010001,
00086 } MMSSCPacketType;
00087
00088 typedef struct {
00089 MMSContext mms;
00090 int outgoing_packet_seq;
00091 char path[256];
00092 char host[128];
00093 int incoming_packet_seq;
00094 int incoming_flags;
00095 int packet_id;
00096 unsigned int header_packet_id;
00097 } MMSTContext;
00098
00100 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type)
00101 {
00102 MMSContext *mms = &mmst->mms;
00103 mms->write_out_ptr = mms->out_buffer;
00104
00105 bytestream_put_le32(&mms->write_out_ptr, 1);
00106 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface);
00107 bytestream_put_le32(&mms->write_out_ptr, 0);
00108 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' '));
00109 bytestream_put_le32(&mms->write_out_ptr, 0);
00110 bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++);
00111 bytestream_put_le64(&mms->write_out_ptr, 0);
00112 bytestream_put_le32(&mms->write_out_ptr, 0);
00113 bytestream_put_le16(&mms->write_out_ptr, packet_type);
00114 bytestream_put_le16(&mms->write_out_ptr, 3);
00115 }
00116
00118 static void insert_command_prefixes(MMSContext *mms,
00119 uint32_t prefix1, uint32_t prefix2)
00120 {
00121 bytestream_put_le32(&mms->write_out_ptr, prefix1);
00122 bytestream_put_le32(&mms->write_out_ptr, prefix2);
00123 }
00124
00126 static int send_command_packet(MMSTContext *mmst)
00127 {
00128 MMSContext *mms = &mmst->mms;
00129 int len= mms->write_out_ptr - mms->out_buffer;
00130 int exact_length = FFALIGN(len, 8);
00131 int first_length= exact_length - 16;
00132 int len8= first_length/8;
00133 int write_result;
00134
00135
00136 AV_WL32(mms->out_buffer + 8, first_length);
00137 AV_WL32(mms->out_buffer + 16, len8);
00138 AV_WL32(mms->out_buffer + 32, len8-2);
00139 memset(mms->write_out_ptr, 0, exact_length - len);
00140
00141
00142 write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length);
00143 if(write_result != exact_length) {
00144 av_log(NULL, AV_LOG_ERROR,
00145 "Failed to write data of length %d: %d (%s)\n",
00146 exact_length, write_result,
00147 write_result < 0 ? strerror(AVUNERROR(write_result)) :
00148 "The server closed the connection");
00149 return AVERROR(EIO);
00150 }
00151
00152 return 0;
00153 }
00154
00155 static void mms_put_utf16(MMSContext *mms, const uint8_t *src)
00156 {
00157 AVIOContext bic;
00158 int size = mms->write_out_ptr - mms->out_buffer;
00159 int len;
00160 ffio_init_context(&bic, mms->write_out_ptr,
00161 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
00162
00163 len = avio_put_str16le(&bic, src);
00164 mms->write_out_ptr += len;
00165 }
00166
00167 static int send_time_test_data(MMSTContext *mmst)
00168 {
00169 start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST);
00170 insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b);
00171 return send_command_packet(mmst);
00172 }
00173
00174 static int send_protocol_select(MMSTContext *mmst)
00175 {
00176 char data_string[256];
00177 MMSContext *mms = &mmst->mms;
00178
00179 start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT);
00180 insert_command_prefixes(mms, 0, 0xffffffff);
00181 bytestream_put_le32(&mms->write_out_ptr, 0);
00182 bytestream_put_le32(&mms->write_out_ptr, 0x00989680);
00183 bytestream_put_le32(&mms->write_out_ptr, 2);
00184 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
00185 (LOCAL_ADDRESS>>24)&0xff,
00186 (LOCAL_ADDRESS>>16)&0xff,
00187 (LOCAL_ADDRESS>>8)&0xff,
00188 LOCAL_ADDRESS&0xff,
00189 "TCP",
00190 LOCAL_PORT);
00191
00192 mms_put_utf16(mms, data_string);
00193 return send_command_packet(mmst);
00194 }
00195
00196 static int send_media_file_request(MMSTContext *mmst)
00197 {
00198 MMSContext *mms = &mmst->mms;
00199 start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST);
00200 insert_command_prefixes(mms, 1, 0xffffffff);
00201 bytestream_put_le32(&mms->write_out_ptr, 0);
00202 bytestream_put_le32(&mms->write_out_ptr, 0);
00203 mms_put_utf16(mms, mmst->path + 1);
00204
00205 return send_command_packet(mmst);
00206 }
00207
00208 static void handle_packet_stream_changing_type(MMSTContext *mmst)
00209 {
00210 MMSContext *mms = &mmst->mms;
00211 av_dlog(NULL, "Stream changing!\n");
00212
00213
00214 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
00215 av_dlog(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id);
00216 }
00217
00218 static int send_keepalive_packet(MMSTContext *mmst)
00219 {
00220
00221 start_command_packet(mmst, CS_PKT_KEEPALIVE);
00222 insert_command_prefixes(&mmst->mms, 1, 0x100FFFF);
00223 return send_command_packet(mmst);
00224 }
00225
00228 static void pad_media_packet(MMSContext *mms)
00229 {
00230 if(mms->remaining_in_len<mms->asf_packet_len) {
00231 int padding_size = mms->asf_packet_len - mms->remaining_in_len;
00232 memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
00233 mms->remaining_in_len += padding_size;
00234 }
00235 }
00236
00238 static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst)
00239 {
00240 int read_result;
00241 MMSSCPacketType packet_type= -1;
00242 MMSContext *mms = &mmst->mms;
00243 for(;;) {
00244 read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8);
00245 if (read_result != 8) {
00246 if(read_result < 0) {
00247 av_log(NULL, AV_LOG_ERROR,
00248 "Error reading packet header: %d (%s)\n",
00249 read_result, strerror(AVUNERROR(read_result)));
00250 packet_type = SC_PKT_CANCEL;
00251 } else {
00252 av_log(NULL, AV_LOG_ERROR,
00253 "The server closed the connection\n");
00254 packet_type = SC_PKT_NO_DATA;
00255 }
00256 return packet_type;
00257 }
00258
00259
00260 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
00261 int length_remaining, hr;
00262
00263 mmst->incoming_flags= mms->in_buffer[3];
00264 read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
00265 if(read_result != 4) {
00266 av_log(NULL, AV_LOG_ERROR,
00267 "Reading command packet length failed: %d (%s)\n",
00268 read_result,
00269 read_result < 0 ? strerror(AVUNERROR(read_result)) :
00270 "The server closed the connection");
00271 return read_result < 0 ? read_result : AVERROR(EIO);
00272 }
00273
00274 length_remaining= AV_RL32(mms->in_buffer+8) + 4;
00275 av_dlog(NULL, "Length remaining is %d\n", length_remaining);
00276
00277 if (length_remaining < 0
00278 || length_remaining > sizeof(mms->in_buffer) - 12) {
00279 av_log(NULL, AV_LOG_ERROR,
00280 "Incoming packet length %d exceeds bufsize %zu\n",
00281 length_remaining, sizeof(mms->in_buffer) - 12);
00282 return AVERROR_INVALIDDATA;
00283 }
00284 read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12,
00285 length_remaining) ;
00286 if (read_result != length_remaining) {
00287 av_log(NULL, AV_LOG_ERROR,
00288 "Reading pkt data (length=%d) failed: %d (%s)\n",
00289 length_remaining, read_result,
00290 read_result < 0 ? strerror(AVUNERROR(read_result)) :
00291 "The server closed the connection");
00292 return read_result < 0 ? read_result : AVERROR(EIO);
00293 }
00294 packet_type= AV_RL16(mms->in_buffer+36);
00295 if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) {
00296 av_log(NULL, AV_LOG_ERROR,
00297 "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
00298 return AVERROR(EINVAL);
00299 }
00300 } else {
00301 int length_remaining;
00302 int packet_id_type;
00303 int tmp;
00304
00305
00306
00307 tmp = AV_RL16(mms->in_buffer + 6);
00308 length_remaining = (tmp - 8) & 0xffff;
00309 mmst->incoming_packet_seq = AV_RL32(mms->in_buffer);
00310 packet_id_type = mms->in_buffer[4];
00311 mmst->incoming_flags = mms->in_buffer[5];
00312
00313 if (length_remaining < 0
00314 || length_remaining > sizeof(mms->in_buffer) - 8) {
00315 av_log(NULL, AV_LOG_ERROR,
00316 "Data length %d is invalid or too large (max=%zu)\n",
00317 length_remaining, sizeof(mms->in_buffer));
00318 return AVERROR_INVALIDDATA;
00319 }
00320 mms->remaining_in_len = length_remaining;
00321 mms->read_in_ptr = mms->in_buffer;
00322 read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
00323 if(read_result != length_remaining) {
00324 av_log(NULL, AV_LOG_ERROR,
00325 "Failed to read packet data of size %d: %d (%s)\n",
00326 length_remaining, read_result,
00327 read_result < 0 ? strerror(AVUNERROR(read_result)) :
00328 "The server closed the connection");
00329 return read_result < 0 ? read_result : AVERROR(EIO);
00330 }
00331
00332
00333 if(packet_id_type == mmst->header_packet_id) {
00334 packet_type = SC_PKT_ASF_HEADER;
00335
00336 if(!mms->header_parsed) {
00337 void *p = av_realloc(mms->asf_header,
00338 mms->asf_header_size + mms->remaining_in_len);
00339 if (!p) {
00340 av_freep(&mms->asf_header);
00341 return AVERROR(ENOMEM);
00342 }
00343 mms->asf_header = p;
00344 memcpy(mms->asf_header + mms->asf_header_size,
00345 mms->read_in_ptr, mms->remaining_in_len);
00346 mms->asf_header_size += mms->remaining_in_len;
00347 }
00348
00349 if (mmst->incoming_flags == 0x04)
00350 continue;
00351 } else if(packet_id_type == mmst->packet_id) {
00352 packet_type = SC_PKT_ASF_MEDIA;
00353 } else {
00354 av_dlog(NULL, "packet id type %d is old.", packet_id_type);
00355 continue;
00356 }
00357 }
00358
00359
00360 if(packet_type == SC_PKT_KEEPALIVE) {
00361 send_keepalive_packet(mmst);
00362 continue;
00363 } else if(packet_type == SC_PKT_STREAM_CHANGING) {
00364 handle_packet_stream_changing_type(mmst);
00365 } else if(packet_type == SC_PKT_ASF_MEDIA) {
00366 pad_media_packet(mms);
00367 }
00368 return packet_type;
00369 }
00370 }
00371
00372 static int mms_safe_send_recv(MMSTContext *mmst,
00373 int (*send_fun)(MMSTContext *mmst),
00374 const MMSSCPacketType expect_type)
00375 {
00376 MMSSCPacketType type;
00377 if(send_fun) {
00378 int ret = send_fun(mmst);
00379 if (ret < 0) {
00380 av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
00381 return ret;
00382 }
00383 }
00384
00385 if ((type = get_tcp_server_response(mmst)) != expect_type) {
00386 av_log(NULL, AV_LOG_ERROR,
00387 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
00388 type, expect_type);
00389 return AVERROR_INVALIDDATA;
00390 } else {
00391 return 0;
00392 }
00393 }
00394
00395 static int send_media_header_request(MMSTContext *mmst)
00396 {
00397 MMSContext *mms = &mmst->mms;
00398 start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST);
00399 insert_command_prefixes(mms, 1, 0);
00400 bytestream_put_le32(&mms->write_out_ptr, 0);
00401 bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
00402 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00403 bytestream_put_le32(&mms->write_out_ptr, 0);
00404 bytestream_put_le32(&mms->write_out_ptr, 0);
00405 bytestream_put_le32(&mms->write_out_ptr, 0);
00406
00407
00408 bytestream_put_le32(&mms->write_out_ptr, 0);
00409 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
00410 bytestream_put_le32(&mms->write_out_ptr, 2);
00411 bytestream_put_le32(&mms->write_out_ptr, 0);
00412
00413 return send_command_packet(mmst);
00414 }
00415
00417 static int send_startup_packet(MMSTContext *mmst)
00418 {
00419 char data_string[256];
00420 MMSContext *mms = &mmst->mms;
00421
00422
00423
00424
00425 snprintf(data_string, sizeof(data_string),
00426 "NSPlayer/7.0.0.1956; {%s}; Host: %s",
00427 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host);
00428
00429 start_command_packet(mmst, CS_PKT_INITIAL);
00430 insert_command_prefixes(mms, 0, 0x0004000b);
00431 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
00432 mms_put_utf16(mms, data_string);
00433 return send_command_packet(mmst);
00434 }
00435
00437 static int send_stream_selection_request(MMSTContext *mmst)
00438 {
00439 int i;
00440 MMSContext *mms = &mmst->mms;
00441
00442 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST);
00443 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num);
00444 for(i= 0; i<mms->stream_num; i++) {
00445 bytestream_put_le16(&mms->write_out_ptr, 0xffff);
00446 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id);
00447 bytestream_put_le16(&mms->write_out_ptr, 0);
00448 }
00449 return send_command_packet(mmst);
00450 }
00451
00452 static int send_close_packet(MMSTContext *mmst)
00453 {
00454 start_command_packet(mmst, CS_PKT_STREAM_CLOSE);
00455 insert_command_prefixes(&mmst->mms, 1, 1);
00456
00457 return send_command_packet(mmst);
00458 }
00459
00461 static int mms_close(URLContext *h)
00462 {
00463 MMSTContext *mmst = (MMSTContext *)h->priv_data;
00464 MMSContext *mms = &mmst->mms;
00465 if(mms->mms_hd) {
00466 send_close_packet(mmst);
00467 ffurl_close(mms->mms_hd);
00468 }
00469
00470
00471 av_free(mms->streams);
00472 av_free(mms->asf_header);
00473
00474 return 0;
00475 }
00476
00477 static int send_media_packet_request(MMSTContext *mmst)
00478 {
00479 MMSContext *mms = &mmst->mms;
00480 start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID);
00481 insert_command_prefixes(mms, 1, 0x0001FFFF);
00482 bytestream_put_le64(&mms->write_out_ptr, 0);
00483 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00484 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00485 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00486 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00487 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00488 bytestream_put_byte(&mms->write_out_ptr, 0x00);
00489
00490 mmst->packet_id++;
00491 bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id);
00492 return send_command_packet(mmst);
00493 }
00494
00495
00496 static void clear_stream_buffers(MMSContext *mms)
00497 {
00498 mms->remaining_in_len = 0;
00499 mms->read_in_ptr = mms->in_buffer;
00500 }
00501
00502 static int mms_open(URLContext *h, const char *uri, int flags)
00503 {
00504 MMSTContext *mmst = h->priv_data;
00505 MMSContext *mms;
00506 int port, err;
00507 char tcpname[256];
00508
00509 h->is_streamed = 1;
00510 mms = &mmst->mms;
00511
00512
00513 av_url_split(NULL, 0, NULL, 0,
00514 mmst->host, sizeof(mmst->host), &port, mmst->path,
00515 sizeof(mmst->path), uri);
00516
00517 if(port<0)
00518 port = 1755;
00519
00520
00521 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
00522 err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
00523 &h->interrupt_callback, NULL);
00524 if (err)
00525 goto fail;
00526
00527 mmst->packet_id = 3;
00528 mmst->header_packet_id = 2;
00529 err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED);
00530 if (err)
00531 goto fail;
00532 err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY);
00533 if (err)
00534 goto fail;
00535 err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED);
00536 if (err)
00537 goto fail;
00538 err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS);
00539 if (err)
00540 goto fail;
00541 err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED);
00542 if (err)
00543 goto fail;
00544 err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER);
00545 if (err)
00546 goto fail;
00547 if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) {
00548 av_log(NULL, AV_LOG_ERROR,
00549 "The server does not support MMST (try MMSH or RTSP)\n");
00550 err = AVERROR(EINVAL);
00551 goto fail;
00552 }
00553 err = ff_mms_asf_header_parser(mms);
00554 if (err) {
00555 av_dlog(NULL, "asf header parsed failed!\n");
00556 goto fail;
00557 }
00558 mms->header_parsed = 1;
00559
00560 if (!mms->asf_packet_len || !mms->stream_num)
00561 goto fail;
00562
00563 clear_stream_buffers(mms);
00564 err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED);
00565 if (err)
00566 goto fail;
00567
00568 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS);
00569 if (err) {
00570 goto fail;
00571 }
00572 av_dlog(NULL, "Leaving open (success)\n");
00573 return 0;
00574 fail:
00575 mms_close(h);
00576 av_dlog(NULL, "Leaving open (failure: %d)\n", err);
00577 return err;
00578 }
00579
00581 static int mms_read(URLContext *h, uint8_t *buf, int size)
00582 {
00583
00584 MMSTContext *mmst = h->priv_data;
00585 MMSContext *mms = &mmst->mms;
00586 int result = 0;
00587
00588 do {
00589 if(mms->asf_header_read_size < mms->asf_header_size) {
00590
00591 result = ff_mms_read_header(mms, buf, size);
00592 } else if(mms->remaining_in_len) {
00593
00594
00595 result = ff_mms_read_data(mms, buf, size);
00596 } else {
00597
00598 int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA);
00599 if (err == 0) {
00600 if(mms->remaining_in_len>mms->asf_packet_len) {
00601 av_log(NULL, AV_LOG_ERROR,
00602 "Incoming pktlen %d is larger than ASF pktsize %d\n",
00603 mms->remaining_in_len, mms->asf_packet_len);
00604 result= AVERROR(EIO);
00605 } else {
00606
00607 result = ff_mms_read_data(mms, buf, size);
00608 if (result == 0) {
00609 av_dlog(NULL, "Read ASF media packet size is zero!\n");
00610 break;
00611 }
00612 }
00613 } else {
00614 av_dlog(NULL, "read packet error!\n");
00615 break;
00616 }
00617 }
00618 } while(!result);
00619 return result;
00620 }
00621
00622 URLProtocol ff_mmst_protocol = {
00623 .name = "mmst",
00624 .url_open = mms_open,
00625 .url_read = mms_read,
00626 .url_close = mms_close,
00627 .priv_data_size = sizeof(MMSTContext),
00628 .flags = URL_PROTOCOL_FLAG_NETWORK,
00629 };