{"action":"created","issue":{"url":"https://api.github.com/repos/fiorix/go-diameter/issues/10","labels_url":"https://api.github.com/repos/fiorix/go-diameter/issues/10/labels{/name}","comments_url":"https://api.github.com/repos/fiorix/go-diameter/issues/10/comments","events_url":"https://api.github.com/repos/fiorix/go-diameter/issues/10/events","html_url":"https://github.com/fiorix/go-diameter/issues/10","id":56802896,"number":10,"title":"Passing custom args to HandleFunc","user":{"login":"dwilkie","id":127583,"avatar_url":"https://avatars.githubusercontent.com/u/127583?v=3","gravatar_id":"","url":"https://api.github.com/users/dwilkie","html_url":"https://github.com/dwilkie","followers_url":"https://api.github.com/users/dwilkie/followers","following_url":"https://api.github.com/users/dwilkie/following{/other_user}","gists_url":"https://api.github.com/users/dwilkie/gists{/gist_id}","starred_url":"https://api.github.com/users/dwilkie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dwilkie/subscriptions","organizations_url":"https://api.github.com/users/dwilkie/orgs","repos_url":"https://api.github.com/users/dwilkie/repos","events_url":"https://api.github.com/users/dwilkie/events{/privacy}","received_events_url":"https://api.github.com/users/dwilkie/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-02-06T11:50:01Z","updated_at":"2015-02-07T23:00:20Z","closed_at":null,"body":"I have the following function which takes a transaction_id and msisdn and tries to create a Credit-ControlRequest:\r\n\r\n```go\r\nfunc Charge(transaction_id string, msisdn string, server_address string) (session_id string, result_code string) {\r\n\r\n  dict.Default.Load(bytes.NewReader(dict.CreditControlXML))\r\n\r\n  // ALL incoming messages are handled here.\r\n  diam.HandleFunc(\"CEA\", OnCEA) // I want to pass the transaction_id and msisdn through here\r\n  diam.HandleFunc(\"CCA\", OnCCA)\r\n  diam.HandleFunc(\"ALL\", OnMSG) // Catch-all.\r\n\r\n  var (\r\n    c   diam.Conn\r\n    err error\r\n  )\r\n  c, err = diam.Dial(server_address, nil, nil)\r\n\r\n  if err != nil {\r\n    log.Fatal(err)\r\n  }\r\n\r\n  go NewClient(c)\r\n\r\n  // Wait until the server kicks us out.\r\n\r\n  <-c.(diam.CloseNotifier).CloseNotify()\r\n  log.Println(\"Server disconnected.\")\r\n}\r\n\r\n// I want this function to accept the transaction_id and msisdn as well so I can add it to the CCR AVP\r\nfunc OnCEA(c diam.Conn, m *diam.Message) {\r\n  rc, err := m.FindAVP(avp.ResultCode)\r\n  if err != nil {\r\n    log.Fatal(err)\r\n  }\r\n  if v, _ := rc.Data.(format.Unsigned32); v != diam.Success {\r\n    log.Fatal(\"Unexpected response:\", rc)\r\n  }\r\n\r\n  // Craft a CCR message.\r\n  r := diam.NewRequest(diam.CreditControl, 4, nil)\r\n\r\n// Add AVP's containing transaction_id and msisdn\r\n}\r\n\r\nfunc OnCCA(c diam.Conn, m *diam.Message) {\r\n  // Here I want to return the result_code and session_id extracted from the AVP's\r\n}\r\n```\r\n\r\nI can't set `transaction_id` or `msisdn` to a global variable, since this will cause problems with concurrency. So the only solution I can come up with at the moment is to send both the `CER` and `CCR` in the same function and hardcoding for example `DestinationRealm` instead of using the response in the `CEA`.\r\n\r\nI looked through the RFC but I couldn't see anything in the spec for passing variables through - e.g sending `transaction_id` and `msisdn` in the `CER` and having it returned in the `CEA`.\r\n\r\nAm I missing something simple here?"},"comment":{"url":"https://api.github.com/repos/fiorix/go-diameter/issues/comments/73387594","html_url":"https://github.com/fiorix/go-diameter/issues/10#issuecomment-73387594","issue_url":"https://api.github.com/repos/fiorix/go-diameter/issues/10","id":73387594,"user":{"login":"fiorix","id":129742,"avatar_url":"https://avatars.githubusercontent.com/u/129742?v=3","gravatar_id":"","url":"https://api.github.com/users/fiorix","html_url":"https://github.com/fiorix","followers_url":"https://api.github.com/users/fiorix/followers","following_url":"https://api.github.com/users/fiorix/following{/other_user}","gists_url":"https://api.github.com/users/fiorix/gists{/gist_id}","starred_url":"https://api.github.com/users/fiorix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fiorix/subscriptions","organizations_url":"https://api.github.com/users/fiorix/orgs","repos_url":"https://api.github.com/users/fiorix/repos","events_url":"https://api.github.com/users/fiorix/events{/privacy}","received_events_url":"https://api.github.com/users/fiorix/received_events","type":"User","site_admin":false},"created_at":"2015-02-07T23:00:20Z","updated_at":"2015-02-07T23:00:20Z","body":"\nSure, you can make up a channel and pass it over to the OnCEA handler, and let it block until OnCEA unblocks it.\n\n    CEApass := make(chan struct{})\n    …\n    diam.Handle(“CEA”, OnCEA(MyConnection, CEApass))\n    …\n    // Next line will block forever. You can optionally wrap it around\n    // a select{} to have a timeout, if needed.\n    <- CEApass\n\n    …\n\n    func OnCEA(conn *MyConnection, CEApass chan struct) diam.HandlerFunc {\n        return func(c diam.Conn, m *diam.Message) {\n            …\n            close(CEApass) // This unblocks main.\n        }\n    }\n\nThis should do it. I haven’t tested this code, just typed in so there might be syntax/other errors. See https://golang.org/doc/effective_go.html#channels <https://golang.org/doc/effective_go.html#channels> for more on Go channels.\n\n\n> On Feb 6, 2015, at 9:38 PM, David Wilkie <notifications@github.com> wrote:\n> \n> Ah great stuff thanks Alexandre that solves one issue.\n> \n> So in the client example <https://github.com/fiorix/go-diameter/blob/master/examples/client/client.go> func main() sets up the Handlers then calls NewClient which sends a CER and blocks until the server kicks us out by calling <-c.(diam.CloseNotifier).CloseNotify()\n> \n> I'd like to be able to have main () set up the connection and send a CER. Later when I get a job from the queue I want to be able to send the CCR. I noticed that you use CloseNotify() to block until the server kicks you out.\n> \n> Is there a way to block until for example OnCEA is called without closing the connection in side the handler e.g.\n> \n> func OnCEA(conn *MyConnection) diam.HandlerFunc {\n>         return func(c diam.Conn, m *diam.Message) {                             \n>           conn.peerRealm = m.FindAVP(avp.OriginRealm)\n>           // I don't want to close the connection here but I want to block until this point\n>           // so I can use conn.peerRealm when I get a job to trigger a CCR\n>           c.Close() \n>         }\n> } \n> When I'm done with this I'll update the example to show how this all fits together. Thanks again!\n> \n> —\n> Reply to this email directly or view it on GitHub <https://github.com/fiorix/go-diameter/issues/10#issuecomment-73346131>.\n> \n\n"}}