2023-08-11 13:12:12 +05:00
|
|
|
package amf
|
|
|
|
|
2023-08-15 12:32:44 +05:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
)
|
2023-08-11 13:12:12 +05:00
|
|
|
|
2023-08-21 20:25:54 +05:00
|
|
|
// most are hard-coded checks to make sure the received AMF0 command is what was received
|
|
|
|
|
|
|
|
|
2023-08-11 15:21:49 +05:00
|
|
|
func (amf_obj_root AMFObj) ProcessConnect() (err error) {
|
|
|
|
err = errors.New("Bad AMF connect command")
|
2023-08-17 15:01:12 +05:00
|
|
|
if !check_object(amf_obj_root, 0, "connect") {
|
2023-08-11 15:21:49 +05:00
|
|
|
return
|
2023-08-11 13:12:12 +05:00
|
|
|
}
|
|
|
|
|
2023-08-17 15:01:12 +05:00
|
|
|
if !check_object(amf_obj_root, 1, 1.0) {
|
|
|
|
return
|
2023-08-11 13:12:12 +05:00
|
|
|
}
|
|
|
|
|
2023-08-17 15:01:12 +05:00
|
|
|
|
2023-08-11 13:12:12 +05:00
|
|
|
if _, ok := amf_obj_root[2]; !ok {
|
2023-08-11 15:21:49 +05:00
|
|
|
return
|
2023-08-11 13:12:12 +05:00
|
|
|
} else if _, ok := amf_obj_root[2].(AMFObj); !ok {
|
2023-08-11 15:21:49 +05:00
|
|
|
return
|
2023-08-17 15:01:12 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
if !check_object(amf_obj_root[2].(AMFObj), "app", "live") {
|
2023-08-11 15:21:49 +05:00
|
|
|
return
|
2023-08-11 13:12:12 +05:00
|
|
|
}
|
2023-08-11 15:21:49 +05:00
|
|
|
err = nil
|
|
|
|
return
|
2023-08-11 13:12:12 +05:00
|
|
|
}
|
2023-08-15 12:32:44 +05:00
|
|
|
|
2023-08-15 15:55:41 +05:00
|
|
|
func (amf_obj_root AMFObj) ProcessCreateStream(trans_id *float64) (err error) {
|
|
|
|
err = errors.New("Bad AMF create stream")
|
2023-08-17 15:01:12 +05:00
|
|
|
if !check_object(amf_obj_root, 0, "createStream") {
|
2023-08-15 15:55:41 +05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := amf_obj_root[1]; !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
transac_id_float, ok := amf_obj_root[1].(float64)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
*trans_id = transac_id_float
|
|
|
|
err = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-08-17 15:01:12 +05:00
|
|
|
func (amf_obj_root AMFObj) ProcessPublish(trans_id *float64, stream_key *string) (err error) {
|
|
|
|
err = errors.New("Bad publish")
|
|
|
|
if !check_object(amf_obj_root, 0, "publish") {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if _, ok := amf_obj_root[1]; !ok {
|
|
|
|
return
|
|
|
|
} else if transac_id_float, ok := amf_obj_root[1].(float64); ok {
|
|
|
|
*trans_id = transac_id_float
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := amf_obj_root[3]; !ok {
|
|
|
|
return
|
|
|
|
} else if stream_key_val, ok := amf_obj_root[3].(string); ok {
|
|
|
|
*stream_key = stream_key_val
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !check_object(amf_obj_root, 4, "live") {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-08-21 20:25:54 +05:00
|
|
|
// Encodes do the reverse, pacakge some data into the corresponding AMF0 message to send
|
|
|
|
|
2023-08-15 13:16:29 +05:00
|
|
|
func EncodeConnectResponse() ([]byte, error) {
|
2023-08-15 12:32:44 +05:00
|
|
|
amf_root_obj := make(AMFObj)
|
|
|
|
amf_root_obj[0] = "_result"
|
|
|
|
amf_root_obj[1] = 1.0
|
|
|
|
|
|
|
|
amf_root_obj[2] = make(AMFObj)
|
|
|
|
amf_prop_obj := amf_root_obj[2].(AMFObj)
|
|
|
|
amf_prop_obj["fmsVer"] = "FMS/3,5,5,2004"
|
|
|
|
amf_prop_obj["capabilities"] = 31.0
|
|
|
|
|
|
|
|
amf_root_obj[3] = make(AMFObj)
|
|
|
|
amf_event_obj := amf_root_obj[3].(AMFObj)
|
|
|
|
amf_event_obj["level"] = "status"
|
|
|
|
amf_event_obj["code"] = "NetConnection.Connect.Success"
|
|
|
|
amf_event_obj["description"] = "Connection Succeeded"
|
|
|
|
amf_event_obj["objectEncoding"] = 0.0
|
|
|
|
|
2023-08-15 13:16:29 +05:00
|
|
|
return Encode(amf_root_obj)
|
2023-08-15 12:32:44 +05:00
|
|
|
}
|
2023-08-15 17:46:41 +05:00
|
|
|
|
|
|
|
func EncodeCreateStreamResponse(trans_id float64) ([]byte, error) {
|
|
|
|
amf_root_obj := make(AMFObj)
|
|
|
|
amf_root_obj[0] = "_result"
|
|
|
|
amf_root_obj[1] = trans_id
|
|
|
|
amf_root_obj[2] = nil
|
|
|
|
amf_root_obj[3] = 1.0
|
|
|
|
|
|
|
|
return Encode(amf_root_obj)
|
|
|
|
}
|
2023-08-17 15:01:12 +05:00
|
|
|
|
|
|
|
func EncodePublishResponse(trans_id float64) ([]byte, error) {
|
|
|
|
amf_root_obj := make(AMFObj)
|
|
|
|
amf_root_obj[0] = "onStatus"
|
|
|
|
amf_root_obj[1] = trans_id
|
|
|
|
amf_root_obj[2] = nil
|
|
|
|
amf_root_obj[3] = make(AMFObj)
|
|
|
|
|
|
|
|
amf_event_obj := amf_root_obj[3].(AMFObj)
|
|
|
|
amf_event_obj["level"] = "status"
|
|
|
|
amf_event_obj["code"] = "NetStream.Publish.Start"
|
|
|
|
amf_event_obj["description"] = "Start Publishing"
|
|
|
|
|
|
|
|
return Encode(amf_root_obj)
|
|
|
|
}
|
|
|
|
|
2023-08-21 20:25:54 +05:00
|
|
|
// helper function, checks if the given key exists for the object and checks if the matching value is the same as the target
|
2023-08-17 15:01:12 +05:00
|
|
|
func check_object(amf_obj AMFObj, key interface{}, target interface{}) (bool) {
|
|
|
|
if val, ok := amf_obj[key]; ok && val == target{
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|