int SendPlayStop(RTMP *r) { RTMPPacket packet; char pbuf[512], *pend = pbuf+sizeof(pbuf); packet.m_nChannel = 0x03; // control channel (invoke) packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; packet.m_nTimeStamp = 0; packet.m_nInfoField2 = 0; packet.m_hasAbsTimestamp = 0; packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; char *enc = packet.m_body; enc = AMF_EncodeString(enc, pend, &av_onStatus); enc = AMF_EncodeNumber(enc, pend, 0); *enc++ = AMF_NULL; *enc++ = AMF_OBJECT; enc = AMF_EncodeNamedString(enc, pend, &av_level, &av_status); enc = AMF_EncodeNamedString(enc, pend, &av_code, &av_NetStream_Play_Stop); enc = AMF_EncodeNamedString(enc, pend, &av_description, &av_Stopped_playing); enc = AMF_EncodeNamedString(enc, pend, &av_details, &r->Link.playpath); enc = AMF_EncodeNamedString(enc, pend, &av_clientid, &av_clientid); *enc++ = 0; *enc++ = 0; *enc++ = AMF_OBJECT_END; packet.m_nBodySize = enc - packet.m_body; return RTMP_SendPacket(r, &packet, FALSE); }
static int SendConnectResult(RTMP *r, double txn) { RTMPPacket packet; char pbuf[384], *pend = pbuf+sizeof(pbuf); AMFObject obj; AMFObjectProperty p, op; AVal av; packet.m_nChannel = 0x03; // control channel (invoke) packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */ packet.m_packetType = 0x14; // INVOKE packet.m_nTimeStamp = 0; packet.m_nInfoField2 = 0; packet.m_hasAbsTimestamp = 0; packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; char *enc = packet.m_body; enc = AMF_EncodeString(enc, pend, &av__result); enc = AMF_EncodeNumber(enc, pend, txn); *enc++ = AMF_OBJECT; STR2AVAL(av, "FMS/3,5,1,525"); enc = AMF_EncodeNamedString(enc, pend, &av_fmsVer, &av); enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 31.0); enc = AMF_EncodeNamedNumber(enc, pend, &av_mode, 1.0); *enc++ = 0; *enc++ = 0; *enc++ = AMF_OBJECT_END; *enc++ = AMF_OBJECT; STR2AVAL(av, "status"); enc = AMF_EncodeNamedString(enc, pend, &av_level, &av); STR2AVAL(av, "NetConnection.Connect.Success"); enc = AMF_EncodeNamedString(enc, pend, &av_code, &av); STR2AVAL(av, "Connection succeeded."); enc = AMF_EncodeNamedString(enc, pend, &av_description, &av); enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r->m_fEncoding); #if 0 STR2AVAL(av, "58656322c972d6cdf2d776167575045f8484ea888e31c086f7b5ffbd0baec55ce442c2fb"); enc = AMF_EncodeNamedString(enc, pend, &av_secureToken, &av); #endif STR2AVAL(p.p_name, "version"); STR2AVAL(p.p_vu.p_aval, "3,5,1,525"); p.p_type = AMF_STRING; obj.o_num = 1; obj.o_props = &p; op.p_type = AMF_OBJECT; STR2AVAL(op.p_name, "data"); op.p_vu.p_object = obj; enc = AMFProp_Encode(&op, enc, pend); *enc++ = 0; *enc++ = 0; *enc++ = AMF_OBJECT_END; packet.m_nBodySize = enc - packet.m_body; return RTMP_SendPacket(r, &packet, FALSE); }
int ExecuteAuthenticationDetails(RTMP *r, AMFObject *proplist, YLENGStream *yle) { long authResult = -1; int i; for (i=0; i<AMF_CountProp(proplist); i++) { AVal name; AMFObjectProperty *prop = AMF_GetProp(proplist, NULL, i); AMFProp_GetName(prop, &name); if (AVMATCH(&name, &av_locatedInBroadcastTerritory)) { yle->locatedInBroadcastTerritory = AMFProp_GetBoolean(prop); } else if (AVMATCH(&name, &av_randomAuth)) { authResult = ((long)AMFProp_GetNumber(prop) + 447537687) % 6834253; } else if (AVMATCH(&name, &av_tvFeeActivated)) { yle->tvFeeActivated = AMFProp_GetBoolean(prop); } } if (authResult != -1) { RTMPPacket packet; char pbuf[128], *pend = pbuf+sizeof(pbuf); packet.m_nChannel = 0x03; // control channel packet.m_headerType = RTMP_PACKET_SIZE_LARGE; packet.m_packetType = 0x11; // FLEX MESSAGE packet.m_nTimeStamp = RTMP_GetTime(); packet.m_nInfoField2 = 0; packet.m_hasAbsTimestamp = 0; packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; char *enc = packet.m_body; *enc++ = 0x00; // Unknown enc = AMF_EncodeString(enc, pend, &av_authenticateRandomNumber); enc = AMF_EncodeNumber(enc, pend, 0); *enc++ = AMF_NULL; enc = AMF_EncodeNumber(enc, pend, (double)authResult); packet.m_nBodySize = enc-packet.m_body; RTMP_Log(RTMP_LOGDEBUG, "sending authenticateRandomNumber"); return RTMP_SendPacket(r, &packet, FALSE); } return FALSE; }
char * amf::AMF_EncodeNamedNumber(char *output, char *outend, const AVal * strName, double dVal) { if (output+2+strName->av_len > outend) return NULL; output = AMF_EncodeInt16(output, outend, strName->av_len); memcpy(output, strName->av_val, strName->av_len); output += strName->av_len; return AMF_EncodeNumber(output, outend, dVal); }
int SendResultNumber(RTMP *r, double txn, double ID) { RTMPPacket packet; char pbuf[256], *pend = pbuf+sizeof(pbuf); packet.m_nChannel = 0x03; // control channel (invoke) packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; packet.m_nTimeStamp = 0; packet.m_nInfoField2 = 0; packet.m_hasAbsTimestamp = 0; packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; char *enc = packet.m_body; enc = AMF_EncodeString(enc, pend, &av__result); enc = AMF_EncodeNumber(enc, pend, txn); *enc++ = AMF_NULL; enc = AMF_EncodeNumber(enc, pend, ID); packet.m_nBodySize = enc - packet.m_body; return RTMP_SendPacket(r, &packet, FALSE); }
int RequestData(RTMP *r, YLENGStream *yle) { RTMPPacket packet; char pbuf[128], *pend = pbuf+sizeof(pbuf); AVal clipID; packet.m_nChannel = 0x03; // control channel packet.m_headerType = RTMP_PACKET_SIZE_LARGE; packet.m_packetType = 0x11; // FLEX MESSAGE packet.m_nTimeStamp = RTMP_GetTime(); packet.m_nInfoField2 = 0; packet.m_hasAbsTimestamp = 0; packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; char *enc = packet.m_body; *enc++ = 0x00; // Unknown enc = AMF_EncodeString(enc, pend, &av_requestData); enc = AMF_EncodeNumber(enc, pend, 0); *enc++ = AMF_NULL; enc = AMF_EncodeString(enc, pend, &av_e0); if ((r->Link.lFlags & RTMP_LF_LIVE) != 0) { char *tmp = malloc(yle->clipID.av_len+12); strcpy(tmp, "streams/fi/"); strncat(tmp, yle->clipID.av_val, yle->clipID.av_len); STR2AVAL(clipID, tmp); enc = AMF_EncodeString(enc, pend, &clipID); free(tmp); } else { char *tmp = malloc(yle->clipID.av_len+2); strcpy(tmp, "/"); strncat(tmp, yle->clipID.av_val, yle->clipID.av_len); STR2AVAL(clipID, tmp); enc = AMF_EncodeString(enc, pend, &clipID); free(tmp); } if (!enc) { RTMP_Log(RTMP_LOGERROR, "Buffer too short in RequestData"); return FALSE; } packet.m_nBodySize = enc-packet.m_body; return RTMP_SendPacket(r, &packet, FALSE); }
uint8_t inline *amf_write_dbl(uint8_t *s, uint8_t *e, double d) { return (uint8_t*)AMF_EncodeNumber((char*)s, (char*)e, d); }