mirror of
https://github.com/number571/hes.git
synced 2026-09-14 02:55:44 +05:00
172 lines
4.1 KiB
Go
172 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
st "github.com/number571/hes/settings"
|
|
|
|
cr "github.com/number571/go-peer/crypto"
|
|
en "github.com/number571/go-peer/encoding"
|
|
lc "github.com/number571/go-peer/local"
|
|
gp "github.com/number571/go-peer/settings"
|
|
)
|
|
|
|
var (
|
|
DATABASE = NewDB("s-hes.db")
|
|
FLCONFIG = NewCFG("s-hes.cfg")
|
|
)
|
|
|
|
func init() {
|
|
go delOldEmailsByTime(24*time.Hour, 6*time.Hour)
|
|
st.HesDefaultInit("localhost:8080")
|
|
fmt.Printf("Server is listening [%s] ...\n\n", st.OPENADDR)
|
|
}
|
|
|
|
func delOldEmailsByTime(deltime, period time.Duration) {
|
|
for {
|
|
DATABASE.DelEmailsByTime(deltime)
|
|
time.Sleep(period)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
http.HandleFunc("/", indexPage)
|
|
http.HandleFunc("/email/send", emailSendPage)
|
|
http.HandleFunc("/email/recv", emailRecvPage)
|
|
http.ListenAndServe(st.OPENADDR, nil)
|
|
}
|
|
|
|
func indexPage(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Macp string `json:"macp"`
|
|
}
|
|
if r.Method != "POST" {
|
|
response(w, 0, "hidden email service")
|
|
return
|
|
}
|
|
if r.ContentLength > int64(st.SETTINGS.Get(gp.SizePack)) {
|
|
response(w, 1, "error: max size")
|
|
return
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&req)
|
|
if err != nil {
|
|
response(w, 2, "error: parse json")
|
|
return
|
|
}
|
|
pasw := cr.NewHasher([]byte(FLCONFIG.Pasw)).Bytes()
|
|
cipher := cr.NewCipher(pasw)
|
|
dect := cipher.Decrypt(en.Base64Decode(req.Macp))
|
|
if !bytes.Equal(en.Uint64ToBytes(st.SETTINGS.Get(gp.MaskRout)), dect) {
|
|
response(w, 3, "error: message authentication code")
|
|
return
|
|
}
|
|
response(w, 0, "success: check connection")
|
|
}
|
|
|
|
func emailSendPage(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Recv string `json:"recv"`
|
|
Data string `json:"data"`
|
|
Macp string `json:"macp"`
|
|
}
|
|
if r.Method != "POST" {
|
|
response(w, 1, "error: method != POST")
|
|
return
|
|
}
|
|
if r.ContentLength > int64(st.SETTINGS.Get(gp.SizePack)) {
|
|
response(w, 2, "error: max size")
|
|
return
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&req)
|
|
if err != nil {
|
|
response(w, 3, "error: parse json")
|
|
return
|
|
}
|
|
pack := lc.Package(req.Data).Deserialize()
|
|
if pack == nil {
|
|
response(w, 4, "error: deserialize package")
|
|
return
|
|
}
|
|
hash := pack.Body.Hash
|
|
puzzle := cr.NewPuzzle(st.SETTINGS.Get(gp.SizeWork))
|
|
if !puzzle.Verify(hash, pack.Body.Npow) {
|
|
response(w, 5, "error: proof of work")
|
|
return
|
|
}
|
|
pasw := cr.NewHasher([]byte(FLCONFIG.Pasw)).Bytes()
|
|
cipher := cr.NewCipher(pasw)
|
|
dech := cipher.Decrypt(en.Base64Decode(req.Macp))
|
|
if !bytes.Equal(hash, dech) {
|
|
response(w, 6, "error: message authentication code")
|
|
return
|
|
}
|
|
err = DATABASE.SetEmail(req.Recv, pack)
|
|
if err != nil {
|
|
response(w, 7, "error: save email")
|
|
return
|
|
}
|
|
for _, conn := range FLCONFIG.Conns {
|
|
go func(conn [2]string) {
|
|
addr := conn[0]
|
|
pasw := cr.NewHasher([]byte(conn[1])).Bytes()
|
|
cipher := cr.NewCipher(pasw)
|
|
req.Macp = en.Base64Encode(cipher.Encrypt(hash))
|
|
resp, err := st.HTCLIENT.Post(
|
|
addr+"/email/send",
|
|
"application/json",
|
|
bytes.NewReader(st.Serialize(req)),
|
|
)
|
|
if err != nil {
|
|
return
|
|
}
|
|
resp.Body.Close()
|
|
}(conn)
|
|
}
|
|
response(w, 0, "success: email saved")
|
|
}
|
|
|
|
func emailRecvPage(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Recv string `json:"recv"`
|
|
Data int `json:"data"`
|
|
}
|
|
if r.Method != "POST" {
|
|
response(w, 1, "error: method != POST")
|
|
return
|
|
}
|
|
if r.ContentLength > int64(st.SETTINGS.Get(gp.SizePack)) {
|
|
response(w, 2, "error: max size")
|
|
return
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&req)
|
|
if err != nil {
|
|
response(w, 3, "error: parse json")
|
|
return
|
|
}
|
|
if req.Data == 0 {
|
|
response(w, 0, fmt.Sprintf("%d", DATABASE.Size(req.Recv)))
|
|
return
|
|
}
|
|
res := DATABASE.GetEmail(req.Data, req.Recv)
|
|
if res == "" {
|
|
response(w, 4, "error: nothing data")
|
|
return
|
|
}
|
|
response(w, 0, res)
|
|
}
|
|
|
|
func response(w http.ResponseWriter, ret int, res string) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
var resp struct {
|
|
Result string `json:"result"`
|
|
Return int `json:"return"`
|
|
}
|
|
resp.Result = res
|
|
resp.Return = ret
|
|
json.NewEncoder(w).Encode(resp)
|
|
}
|