Beispiel #1
0
		public void SendMessage(string handler, IList arguments) {
			BeginUpdate();
			try {
				_so.SendMessage(handler, arguments);
			} finally {
				EndUpdate();
			}

			// Invoke method on registered handler
			string serviceName, serviceMethod;
			int dotPos = handler.LastIndexOf(".");
			if (dotPos != -1) {
				serviceName = handler.Substring(0, dotPos);
				serviceMethod = handler.Substring(dotPos + 1);
			} else {
				serviceName = string.Empty;
				serviceMethod = handler;
			}

			object soHandler = GetServiceHandler(serviceName);
			if (soHandler == null && this.HasParent) {
				// No custom handler, check for service defined in the scope's context
				IScopeContext context = this.Parent.Context;
				try {
					//Search for a handler only if there is a service name specified
					if (serviceName != string.Empty) {
						// The type must have a name of "SharedObjectName.DottedServiceName"
						soHandler = ObjectFactory.CreateInstance(_so.Name + "." + serviceName);
					}
				} catch (Exception) {
					// No such type.
					log.Debug(__Res.GetString(__Res.Type_InitError, _so.Name + "." + serviceName));
				}
			}

			if (soHandler != null) {
				MethodInfo mi = MethodHandler.GetMethod(soHandler.GetType(), serviceMethod, arguments);
				if (mi != null) {
					ParameterInfo[] parameterInfos = mi.GetParameters();
					object[] args = new object[parameterInfos.Length];
					arguments.CopyTo(args, 0);
					TypeHelper.NarrowValues(args, parameterInfos);
					try {
						InvocationHandler invocationHandler = new InvocationHandler(mi);
						object result = invocationHandler.Invoke(soHandler, args);
					} catch (Exception exception) {
						log.Error(__Res.GetString(__Res.ServiceHandler_InvocationFailed, serviceMethod, handler), exception);
					}
				}
			}

			// Notify server listeners
			foreach (ISharedObjectListener listener in _serverListeners) {
				listener.OnSharedObjectSend(this, handler, arguments);
			}
		}
Beispiel #2
0
		public override void Invoke(AMFContext context) {
			MessageOutput messageOutput = context.MessageOutput;
			for (int i = 0; i < context.AMFMessage.BodyCount; i++) {
				AMFBody amfBody = context.AMFMessage.GetBodyAt(i);
				ResponseBody responseBody = null;
				//Check for Flex2 messages and skip
				if (amfBody.IsEmptyTarget)
					continue;

				if (amfBody.IsDebug)
					continue;
				if (amfBody.IsDescribeService) {
					responseBody = new ResponseBody();
					responseBody.IgnoreResults = amfBody.IgnoreResults;
					responseBody.Target = amfBody.Response + AMFBody.OnResult;
					responseBody.Response = null;
					DescribeService describeService = new DescribeService(amfBody);
					responseBody.Content = describeService.GetDescription();
					messageOutput.AddBody(responseBody);
					continue;
				}

				//Check if response exists.
				responseBody = messageOutput.GetResponse(amfBody);
				if (responseBody != null) {
					continue;
				}

				try {
					MessageBroker messageBroker = _endpoint.GetMessageBroker();
					RemotingService remotingService = messageBroker.GetService(RemotingService.RemotingServiceId) as RemotingService;
					if (remotingService == null) {
						string serviceNotFound = __Res.GetString(__Res.Service_NotFound, RemotingService.RemotingServiceId);
						responseBody = new ErrorResponseBody(amfBody, new FluorineException(serviceNotFound));
						messageOutput.AddBody(responseBody);
						if (log.IsErrorEnabled)
							log.Error(serviceNotFound);
						continue;
					}
					Destination destination = null;
					if (destination == null)
						destination = remotingService.GetDestinationWithSource(amfBody.TypeName);
					if (destination == null)
						destination = remotingService.DefaultDestination;
					//At this moment we got a destination with the exact source or we have a default destination with the "*" source.
					if (destination == null) {
						string destinationNotFound = __Res.GetString(__Res.Destination_NotFound, amfBody.TypeName);
						responseBody = new ErrorResponseBody(amfBody, new FluorineException(destinationNotFound));
						messageOutput.AddBody(responseBody);
						if (log.IsErrorEnabled)
							log.Error(destinationNotFound);
						continue;
					}

					try {
						remotingService.CheckSecurity(destination);
					} catch (UnauthorizedAccessException exception) {
						responseBody = new ErrorResponseBody(amfBody, exception);
						if (log.IsDebugEnabled)
							log.Debug(exception.Message);
						continue;
					}

					//Cache check
					string source = amfBody.TypeName + "." + amfBody.Method;
					IList parameterList = amfBody.GetParameterList();
					string key = GodLesZ.Library.Amf.Configuration.CacheMap.GenerateCacheKey(source, parameterList);
					if (FluorineConfiguration.Instance.CacheMap.ContainsValue(key)) {
						object result = GodLesZ.Library.Amf.Configuration.FluorineConfiguration.Instance.CacheMap.Get(key);
						if (result != null) {
							if (log != null && log.IsDebugEnabled)
								log.Debug(__Res.GetString(__Res.Cache_HitKey, source, key));
							responseBody = new ResponseBody(amfBody, result);
							messageOutput.AddBody(responseBody);
							continue;
						}
					}

					FactoryInstance factoryInstance = destination.GetFactoryInstance();
					factoryInstance.Source = amfBody.TypeName;
					if (FluorineContext.Current.ActivationMode != null)//query string can override the activation mode
						factoryInstance.Scope = FluorineContext.Current.ActivationMode;
					object instance = factoryInstance.Lookup();

					if (instance != null) {
						try {
							bool isAccessible = TypeHelper.GetTypeIsAccessible(instance.GetType());
							if (!isAccessible) {
								string msg = __Res.GetString(__Res.Type_InitError, amfBody.TypeName);
								if (log.IsErrorEnabled)
									log.Error(msg);
								responseBody = new ErrorResponseBody(amfBody, new FluorineException(msg));
								messageOutput.AddBody(responseBody);
								continue;
							}

							MethodInfo mi = null;
							if (!amfBody.IsRecordsetDelivery) {
								mi = MethodHandler.GetMethod(instance.GetType(), amfBody.Method, amfBody.GetParameterList());
							} else {
								//will receive recordsetid only (ignore)
								mi = instance.GetType().GetMethod(amfBody.Method);
							}
							if (mi != null) {
								object[] roleAttributes = mi.GetCustomAttributes(typeof(RoleAttribute), true);
								if (roleAttributes != null && roleAttributes.Length == 1) {
									RoleAttribute roleAttribute = roleAttributes[0] as RoleAttribute;
									string[] roles = roleAttribute.Roles.Split(',');

									bool authorized = messageBroker.LoginManager.DoAuthorization(roles);
									if (!authorized)
										throw new UnauthorizedAccessException(__Res.GetString(__Res.Security_AccessNotAllowed));
								}

								#region Invocation handling
								PageSizeAttribute pageSizeAttribute = null;
								MethodInfo miCounter = null;
								object[] pageSizeAttributes = mi.GetCustomAttributes(typeof(PageSizeAttribute), true);
								if (pageSizeAttributes != null && pageSizeAttributes.Length == 1) {
									pageSizeAttribute = pageSizeAttributes[0] as PageSizeAttribute;
									miCounter = instance.GetType().GetMethod(amfBody.Method + "Count");
									if (miCounter != null && miCounter.ReturnType != typeof(System.Int32))
										miCounter = null; //check signature
								}
								ParameterInfo[] parameterInfos = mi.GetParameters();
								//Try to handle missing/optional parameters.
								object[] args = new object[parameterInfos.Length];
								if (!amfBody.IsRecordsetDelivery) {
									if (args.Length != parameterList.Count) {
										string msg = __Res.GetString(__Res.Arg_Mismatch, parameterList.Count, mi.Name, args.Length);
										if (log != null && log.IsErrorEnabled)
											log.Error(msg);
										responseBody = new ErrorResponseBody(amfBody, new ArgumentException(msg));
										messageOutput.AddBody(responseBody);
										continue;
									}
									parameterList.CopyTo(args, 0);
									if (pageSizeAttribute != null) {
										PagingContext pagingContext = new PagingContext(pageSizeAttribute.Offset, pageSizeAttribute.Limit);
										PagingContext.SetPagingContext(pagingContext);
									}
								} else {
									if (amfBody.Target.EndsWith(".release")) {
										responseBody = new ResponseBody(amfBody, null);
										messageOutput.AddBody(responseBody);
										continue;
									}
									string recordsetId = parameterList[0] as string;
									string recordetDeliveryParameters = amfBody.GetRecordsetArgs();
									byte[] buffer = System.Convert.FromBase64String(recordetDeliveryParameters);
									recordetDeliveryParameters = System.Text.Encoding.UTF8.GetString(buffer);
									if (recordetDeliveryParameters != null && recordetDeliveryParameters != string.Empty) {
										string[] stringParameters = recordetDeliveryParameters.Split(new char[] { ',' });
										for (int j = 0; j < stringParameters.Length; j++) {
											if (stringParameters[j] == string.Empty)
												args[j] = null;
											else
												args[j] = stringParameters[j];
										}
										//TypeHelper.NarrowValues(argsStore, parameterInfos);
									}
									PagingContext pagingContext = new PagingContext(System.Convert.ToInt32(parameterList[1]), System.Convert.ToInt32(parameterList[2]));
									PagingContext.SetPagingContext(pagingContext);
								}

								TypeHelper.NarrowValues(args, parameterInfos);

								try {
									InvocationHandler invocationHandler = new InvocationHandler(mi);
									object result = invocationHandler.Invoke(instance, args);

									if (FluorineConfiguration.Instance.CacheMap != null && FluorineConfiguration.Instance.CacheMap.ContainsCacheDescriptor(source)) {
										//The result should be cached
										CacheableObject cacheableObject = new CacheableObject(source, key, result);
										FluorineConfiguration.Instance.CacheMap.Add(cacheableObject.Source, cacheableObject.CacheKey, cacheableObject);
										result = cacheableObject;
									}
									responseBody = new ResponseBody(amfBody, result);

									if (pageSizeAttribute != null) {
										int totalCount = 0;
										string recordsetId = null;

										IList list = amfBody.GetParameterList();
										string recordetDeliveryParameters = null;
										if (!amfBody.IsRecordsetDelivery) {
											//fist call paging
											object[] argsStore = new object[list.Count];
											list.CopyTo(argsStore, 0);
											recordsetId = System.Guid.NewGuid().ToString();
											if (miCounter != null) {
												//object[] counterArgs = new object[0];
												totalCount = (int)miCounter.Invoke(instance, args);
											}
											string[] stringParameters = new string[argsStore.Length];
											for (int j = 0; j < argsStore.Length; j++) {
												if (argsStore[j] != null)
													stringParameters[j] = argsStore[j].ToString();
												else
													stringParameters[j] = string.Empty;
											}
											recordetDeliveryParameters = string.Join(",", stringParameters);
											byte[] buffer = System.Text.Encoding.UTF8.GetBytes(recordetDeliveryParameters);
											recordetDeliveryParameters = System.Convert.ToBase64String(buffer);
										} else {
											recordsetId = amfBody.GetParameterList()[0] as string;
										}
										if (result is DataTable) {
											DataTable dataTable = result as DataTable;
											dataTable.ExtendedProperties["TotalCount"] = totalCount;
											dataTable.ExtendedProperties["Service"] = recordetDeliveryParameters + "/" + amfBody.Target;
											dataTable.ExtendedProperties["RecordsetId"] = recordsetId;
											if (amfBody.IsRecordsetDelivery) {
												dataTable.ExtendedProperties["Cursor"] = Convert.ToInt32(list[list.Count - 2]);
												dataTable.ExtendedProperties["DynamicPage"] = true;
											}
										}
									}
								} catch (UnauthorizedAccessException exception) {
									responseBody = new ErrorResponseBody(amfBody, exception);
									if (log.IsDebugEnabled)
										log.Debug(exception.Message);
								} catch (Exception exception) {
									if (exception is TargetInvocationException && exception.InnerException != null)
										responseBody = new ErrorResponseBody(amfBody, exception.InnerException);
									else
										responseBody = new ErrorResponseBody(amfBody, exception);
									if (log.IsDebugEnabled)
										log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, exception.Message));
								}
								#endregion Invocation handling
							} else
								responseBody = new ErrorResponseBody(amfBody, new MissingMethodException(amfBody.TypeName, amfBody.Method));
						} finally {
							factoryInstance.OnOperationComplete(instance);
						}
					} else
						responseBody = new ErrorResponseBody(amfBody, new TypeInitializationException(amfBody.TypeName, null));
				} catch (Exception exception) {
					if (log != null && log.IsErrorEnabled)
						log.Error(exception.Message, exception);
					responseBody = new ErrorResponseBody(amfBody, exception);
				}
				messageOutput.AddBody(responseBody);
			}
		}
Beispiel #3
0
		public override object Invoke(IMessage message) {
			object result = null;
			RemotingMessage remotingMessage = message as RemotingMessage;
			string operation = remotingMessage.operation;
			string className = this.DestinationDefinition.Properties.Source;
			//This property is provided for backwards compatibility. The best practice, however, is to not expose the underlying source of a 
			//RemoteObject destination on the client and only one source to a destination.
			if (remotingMessage.source != null && remotingMessage.source != string.Empty) {
				if (className == "*")
					className = remotingMessage.source;
				if (className != remotingMessage.source) {
					string msg = __Res.GetString(__Res.Type_MismatchMissingSource, remotingMessage.source, this.DestinationDefinition.Properties.Source as string);
					throw new MessageException(msg, new TypeLoadException(msg));
				}
			}

			if (className == null)
				throw new TypeInitializationException("null", null);

			//Service mapping obsolete for Flex Remoting
			/*
			if (FluorineConfiguration.Instance.ServiceMap != null)
			{
				string method = remotingMessage.operation;
				if (FluorineConfiguration.Instance.ServiceMap.Contains(className))
				{
					string serviceLocation = FluorineConfiguration.Instance.ServiceMap.GetServiceLocation(className);
					method = FluorineConfiguration.Instance.ServiceMap.GetMethod(className, method);
					if (log != null && log.IsDebugEnabled)
						log.Debug(__Res.GetString(__Res.Service_Mapping, className + "." + remotingMessage.operation, serviceLocation + "." + method));

					className = serviceLocation;
					remotingMessage.operation = method;
				}
			}
			*/
			//Cache check
			string source = className + "." + operation;
			IList parameterList = remotingMessage.body as IList;
			string key = GodLesZ.Library.Amf.Configuration.CacheMap.GenerateCacheKey(source, parameterList);
			if (FluorineConfiguration.Instance.CacheMap.ContainsValue(key)) {
				result = GodLesZ.Library.Amf.Configuration.FluorineConfiguration.Instance.CacheMap.Get(key);
				if (result != null) {
					if (log != null && log.IsDebugEnabled)
						log.Debug(__Res.GetString(__Res.Cache_HitKey, operation, key));
					return result;
				}
			}

			FactoryInstance factoryInstance = this.Destination.GetFactoryInstance();
			factoryInstance.Source = className;
			object instance = factoryInstance.Lookup();

			if (instance != null) {
				try {
					Type type = instance.GetType();
					bool isAccessible = TypeHelper.GetTypeIsAccessible(type);
					if (!isAccessible) {
						string msg = __Res.GetString(__Res.Type_InitError, type.FullName);
						throw new MessageException(msg, new TypeLoadException(msg));
					}

					MethodInfo mi = MethodHandler.GetMethod(type, operation, parameterList);
					if (mi != null) {
						try {
							//Messagebroker checked xml configured security, check attributes too
							object[] roleAttributes = mi.GetCustomAttributes(typeof(RoleAttribute), true);
							if (roleAttributes != null && roleAttributes.Length == 1) {
								RoleAttribute roleAttribute = roleAttributes[0] as RoleAttribute;
								string[] roles = roleAttribute.Roles.Split(',');

								bool authorized = this.Destination.Service.GetMessageBroker().LoginManager.DoAuthorization(roles);
								if (!authorized)
									throw new UnauthorizedAccessException(__Res.GetString(__Res.Security_AccessNotAllowed));
							}

							ParameterInfo[] parameterInfos = mi.GetParameters();
							object[] args = new object[parameterInfos.Length];
							parameterList.CopyTo(args, 0);
							TypeHelper.NarrowValues(args, parameterInfos);
							InvocationHandler invocationHandler = new InvocationHandler(mi);
							result = invocationHandler.Invoke(instance, args);
						} catch (TargetInvocationException exception) {
							MessageException messageException = null;
							if (exception.InnerException is MessageException)
								messageException = exception.InnerException as MessageException;//User code throws MessageException
							else
								messageException = new MessageException(exception.InnerException);

							if (log.IsDebugEnabled)
								log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, messageException.Message));
							return messageException.GetErrorMessage();
							//Do not throw here, we do not want to log user code exceptions.
							//throw messageException;
						}

					} else
						throw new MessageException(new MissingMethodException(className, operation));
				} catch (MessageException) {
					throw;
				} catch (Exception exception) {
					MessageException messageException = new MessageException(exception);
					throw messageException;
				} finally {
					factoryInstance.OnOperationComplete(instance);
				}
			} else
				throw new MessageException(new TypeInitializationException(className, null));

			if (FluorineConfiguration.Instance.CacheMap != null && FluorineConfiguration.Instance.CacheMap.ContainsCacheDescriptor(source)) {
				//The result should be cached
				CacheableObject cacheableObject = new CacheableObject(source, key, result);
				FluorineConfiguration.Instance.CacheMap.Add(cacheableObject.Source, cacheableObject.CacheKey, cacheableObject);
				result = cacheableObject;
			}
			return result;
		}
Beispiel #4
0
		public void OnStreamEvent(Notify notify) {
			bool onStatus = notify.ServiceCall.ServiceMethodName.Equals("onStatus");
			if (!onStatus) {
				if (notify.ServiceCall.ServiceMethodName.Equals("onMetaData"))
					RaiseOnMetaData(notify.ServiceCall.Arguments[0] as IDictionary);
				if (notify.ServiceCall.ServiceMethodName.Equals("onPlayStatus"))
					RaiseOnPlayStatus(notify.ServiceCall.Arguments[0] as IDictionary);

				MethodInfo mi = MethodHandler.GetMethod(_client.GetType(), notify.ServiceCall.ServiceMethodName, notify.ServiceCall.Arguments, false, false);
				if (mi != null) {
					ParameterInfo[] parameterInfos = mi.GetParameters();
					object[] args = new object[parameterInfos.Length];
					notify.ServiceCall.Arguments.CopyTo(args, 0);
					TypeHelper.NarrowValues(args, parameterInfos);
					try {
						InvocationHandler invocationHandler = new InvocationHandler(mi);
						object result = invocationHandler.Invoke(_client, args);
					} catch (Exception exception) {
						notify.ServiceCall.Exception = exception;
						notify.ServiceCall.Status = GodLesZ.Library.Amf.Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION;
						//log.Error("Error while invoking method " + call.ServiceMethodName + " on client", exception);
					}
				} else {
					string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, notify.ServiceCall.ServiceMethodName);
					this.RaiseNetStatus(new FluorineException(msg));
				}
			} else {
				object[] args = notify.ServiceCall.Arguments;
				ASObject statusASO = null;
				if ((args != null) && (args.Length > 0))
					statusASO = args[0] as ASObject;
				this.RaiseNetStatus(statusASO);
			}
		}
Beispiel #5
0
		public bool Invoke(IServiceCall call, object service) {
			string serviceMethod = call.ServiceMethodName;
			object[] arguments = call.Arguments;

			// First, search for method with exact parameter type match
			MethodInfo mi = MethodHandler.GetMethod(service.GetType(), serviceMethod, arguments, true, false, false);
			if (mi == null) {
				// Second, search for method with type conversions
				// This second call will trace 'suitable method' errors too
				mi = MethodHandler.GetMethod(service.GetType(), serviceMethod, arguments, false, false, true);
				if (mi == null) {
					string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, serviceMethod);
					call.Status = Call.STATUS_METHOD_NOT_FOUND;
					call.Exception = new FluorineException(msg);
					return false;
				}
			}

			try {
				ParameterInfo[] parameterInfos = mi.GetParameters();
				object[] parameters = new object[parameterInfos.Length];
				arguments.CopyTo(parameters, 0);
				TypeHelper.NarrowValues(parameters, parameterInfos);

				object result = null;
				if (mi.ReturnType == typeof(void)) {
					InvocationHandler invocationHandler = new InvocationHandler(mi);
					invocationHandler.Invoke(service, parameters);
					call.Status = Call.STATUS_SUCCESS_VOID;
				} else {
					InvocationHandler invocationHandler = new InvocationHandler(mi);
					result = invocationHandler.Invoke(service, parameters);
					call.Status = result == null ? Call.STATUS_SUCCESS_NULL : Call.STATUS_SUCCESS_RESULT;
				}
				if (call is IPendingServiceCall)
					(call as IPendingServiceCall).Result = result;
			} catch (SecurityException exception) {
				call.Exception = exception;
				call.Status = Call.STATUS_ACCESS_DENIED;
				if (log.IsDebugEnabled)
					log.Debug(exception.Message);
				return false;
			} catch (UnauthorizedAccessException exception) {
				call.Exception = exception;
				call.Status = Call.STATUS_ACCESS_DENIED;
				if (log.IsDebugEnabled)
					log.Debug(exception.Message);
				return false;
			} catch (TargetInvocationException exception) {
				call.Exception = exception.InnerException;
				call.Status = Call.STATUS_INVOCATION_EXCEPTION;
				if (log.IsDebugEnabled)
					log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, exception.InnerException.Message));
				return false;
			} catch (Exception exception) {
				call.Exception = exception;
				call.Status = Call.STATUS_GENERAL_EXCEPTION;
				if (log.IsDebugEnabled)
					log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, exception.Message));
				return false;
			}
			return true;
		}