Red5 Source Analysis---8

Source: Internet
Author: User

Red5 Source Analysis-Server processing CreateStream command

After the server receives the CreateStream command, it passes through the filter layer and finally calls the Basertmphandler messagereceived function.

public void messagereceived (Rtmpconnection conn, Packet Packet) throws Exception {if(conn! = null) {Irtmpevent message = NULL;Try{message = Packet.getmessage ();                Final Header Header = Packet.getheader ();                Final number Streamid = Header.getstreamid ();                Final Channel channel = Conn.getchannel (Header.getchannelid ());                Final Iclientstream stream = Conn.getstreambyid (Streamid);                Conn.setstreamid (Streamid);                Conn.messagereceived ();                Message.setsource (conn); Final byte Headerdatatype = Header.getdatatype ();Switch(Headerdatatype) {...Case Type_invoke:case Type_flex_message:oncommand (conn, channel, header, (invo                        KE) message); Ipendingservicecall call = ((Invoke) message). Getcall ();if(Message.getheader (). Getstreamid (). Intvalue ()! =0&& call.getservicename () = = null && StreamAction.PUBLISH.equals (Call.getservicemethodname ())) {if(Stream! = null)                            {((Ieventdispatcher) stream). dispatchevent (message); }                        } Break;...Default:}if(Message instanceof Unknown) {}} catch (Throwable t) {}...}    }

The message of the CreateStream command belongs to the Type_invoke message, and finally the OnCommand function is called, OnCommand is defined in Rtmphandler, and a portion of the Red5 code is described in OnCommand source analysis-5. Now look at the other part,

    protected void OnCommand(Rtmpconnection conn, channel Channel, Header Source, ICommand command) {FinalIServiceCall call = Command.getcall ();FinalString action = Call.getservicemethodname ();if("_result". Equals (action) | |"_error". Equals (Action) {Handlependingcallresult (conn, (Invoke) command);return; }BooleanDisconnectonreturn =false;BooleanConnected = conn.isconnected ();if(connected) {if(Call.getservicename () = =NULL{Streamaction streamaction = Streamaction.getenum (action);if(dispatchstreamactions) {Try{Conn.getscope (). GetHandler (). Handleevent (NewStreamactionevent (streamaction)); }Catch(Exception ex) {                    }                }Switch(streamaction) { CaseDISCONNECT:conn.close (); Break; CaseCreate_stream: CaseInit_stream: CaseClose_stream: CaseRelease_stream: CaseDelete_stream: CasePUBLISH: CasePLAY: CasePLAY2: CaseSEEK: CasePAUSE: CasePause_raw: CaseReceive_video: CaseReceive_audio:istreamservice Streamservice = (istreamservice) scopeutils.getscopeservice (Conn.getS Cope (), Istreamservice.class, Streamservice.class);Try{if(Invokecall (conn, call, Streamservice)) {                            }Else{                            }                        }Catch(Throwable err) {                            ...                        } Break;default: Invokecall (conn, call); }            }Else{Invokecall (conn, call); }        }Else{             ...        }if(CommandinstanceofInvoke) {if((Source.getstreamid (). Intvalue ()! =0) && (call.getstatus () = = Call.status_success_void | | call.getstatus () = = Call.status_success_null)) {return; }BooleanSendresult =true;if(CallinstanceofIpendingservicecall) {Ipendingservicecall PSC = (ipendingservicecall) call; Object result = Psc.getresult ();if(ResultinstanceofDeferredresult) {Deferredresult Dr = (Deferredresult) result;                    Dr.setservicecall (PSC);                    Dr.setchannel (channel);                    Dr.settransactionid (Command.gettransactionid ());                    Conn.registerdeferredresult (DR); Sendresult =false; }            }if(Sendresult) {Invoke reply =NewInvoke ();                Reply.setcall (call);                Reply.settransactionid (Command.gettransactionid ()); Channel.write (reply);if(Disconnectonreturn)                {Conn.close (); }            }        }    }

OnCommand two parts of the code in the "Red5 Source analysis-5" has been seen, the difference is that there is a server scope has been connected, so isconnected returns True. And then down is calling Scopeutils's getscopeservice to get Streamservice,getscopeservice defined as follows

     Public StaticObject Getscopeservice (IscopeScope, class<?> intf, Class<?> defaultclass, Boolean checkhandler) {String attr = IPERSISTABLE.TRANSIENT_PR Efix + Service_cache_prefix + intf.getcanonicalname ();if(Scope. Hasattribute (attr)) {return Scope. getattribute (attr); } Object Handler =NULL;if(Checkhandler) {Iscope current =Scope; while(Current! =NULL) {Iscopehandler Scopehandler = Current.gethandler ();if(Intf.isinstance (Scopehandler)) {handler = Scopehandler; Break; }if(!current.hasparent ()) { Break;            } current = Current.getparent (); }        }if(Handler = =NULL&& Iscopeservice.class. IsAssignableFrom (intf)) {Field key =NULL; Object ServiceName =NULL;Try{key = Intf.getfield ("Bean_name"); ServiceName = Key.get (NULL);if(ServiceName instanceof String) {handler = Getscopeservice (Scope, (String) serviceName, Defaultclass); }            }Catch(Exception e) {            }        }if(Handler = =NULL&& Defaultclass! =NULL) {Try{handler = Defaultclass.newinstance (); }Catch(Exception e) {            }        }Scope. SetAttribute (attr, handler);returnHandler }

First, we will try to get the instantiated streamservice from the cache of scope, and if not, look for the handler in the parent class from that scope (as you know from the previous chapters, At this point the basic handler is Corehandler), and then down is to see the bean_name, and try to get or initialize the class through spring, if not, and finally directly through the Java instantiation.
Back to the OnCommand, assuming that the streamservice, the following through the Invokecall began to deal with,

    privatebooleaninvokeCall(RTMPConnection conn, IServiceCall call, Object service) {        final IScope scope = conn.getScope();        final IContext context = scope.getContext();        return context.getServiceInvoker().invoke(call, service);    }

Based on the analysis of the previous chapters, The Context obtained here is org.red5.server.Context, according to the configuration of Red5-default.xml, Getserviceinvoker returns Org.red5.server.service.ServiceInvoker, so the following To see its invoke function,

Public boolean invoke (IServiceCall.ObjectService) {Iconnection conn = red5.getconnectionlocal ();StringMethodName = Call.getservicemethodname ();if(Methodname.charat (0) ==' @ ') {MethodName = Methodname.substring (1); }Object[] args = call.getarguments ();Object[] argswithconnection;if(Args! =NULL) {argswithconnection =New Object[Args.length +1]; argswithconnection[0] = conn; for(int i =0; i < args.length; i++) {argswithconnection[i +1] = Args[i]; }        }Else{argswithconnection =New Object[] {conn}; }Object[] Methodresult =NULL; Methodresult = reflectionutils.findmethodwithexactparameters (service, MethodName, argswithconnection);if(Methodresult.length = =0|| methodresult[0] ==NULL{Methodresult = reflectionutils.findmethodwithexactparameters (service, methodName, args);if(Methodresult.length = =0|| methodresult[0] ==NULL{Methodresult = reflectionutils.findmethodwithlistparameters (service, MethodName, argswithconnection);if(Methodresult.length = =0|| methodresult[0] ==NULL{Methodresult = reflectionutils.findmethodwithlistparameters (service, methodName, args);if(Methodresult.length = =0|| methodresult[0] ==NULL) {call.setstatus (call.status_method_not_found);if(Args! =NULL&& args.length >0) {Call.setexception (NewMethodnotfoundexception (MethodName, args)); }Else{Call.setexception (NewMethodnotfoundexception (MethodName)); }return false; }                }            }        }Objectresult =NULL; Method method = (method) methodresult[0];Object[] params = (Object[]) methodresult[1];Try{if(Method.isannotationpresent (Declareprivate.class)) {Throw NewNotallowedexception ("Access denied, method is private"); } final declareprotected annotation = method.getannotation (Declareprotected.class);if(Annotation! =NULL) {if(!conn.getclient (). haspermission (conn, annotation.permission ())) {Throw NewNotallowedexception ("Access denied, method is protected"); }            }if(Method.getreturntype (). Equals (Void.type))                {Method.invoke (service, params);            Call.setstatus (call.status_success_void); }Else{result = Method.invoke (service, params); Call.setstatus (Result = =NULL?            Call.STATUS_SUCCESS_NULL:Call.STATUS_SUCCESS_RESULT); }if(CallinstanceofIpendingservicecall) {((Ipendingservicecall) call). Setresult (result); }        }Catch(Exception e) {            ...return false; }return true; }

This is to facilitate reading, the abnormal part of the rewrite. Although this code is a little bit longer, but actually do things very simple, is to get the method from Streamservice, and call the method, the specific code can be analyzed by itself, because it is not only to find once, is one time to relax the condition to find, find the method, call its invoke execution method, and processes the return value. The next step is to call Streamservice's CreateStream method,

    publiccreateStream() {        IConnection conn = Red5.getConnectionLocal();        ifinstanceof IStreamCapableConnection) {            try {                Number streamId = ((IStreamCapableConnection) conn).reserveStreamId();                }                return streamId;            catch (IndexOutOfBoundsException e) {                return -1;            }        }        return -1;    }

This will simply call Reservestreamid to get a random streamid and return,

    publicreserveStreamId() {        double1.0d;        for (; d < MAX_RESERVED_STREAMS; d++) {            if (reservedStreams.add(d)) {                break;            }        }        if (d == MAX_RESERVED_STREAMS) {            thrownew IndexOutOfBoundsException("Unable to reserve new stream");        }        return d;    }

Back in the previous Invoke method, the RESULT of the last call saved the ID of the stream that was just allocated, and the status is Status_success_result and then returned to the client. As can be seen from here, CreateStream is only responsible for assigning an ID, no file creation, socket creation, and so on.

Red5 Source Analysis---8

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.